wifi: Store BARs and MU-BARs in the MAC queues

This commit is contained in:
Stefano Avallone
2022-11-28 10:01:31 +01:00
committed by Stefano Avallone
parent 535c5798f0
commit 17a8c836e3
9 changed files with 237 additions and 96 deletions

View File

@@ -708,7 +708,7 @@ BlockAckManager::NotifyDiscardedMpdu(Ptr<const WifiMpdu> mpdu)
hdr.SetNoRetry();
hdr.SetNoMoreFragments();
ScheduleBar(Create<const WifiMpdu>(bar, hdr));
ScheduleBar(Create<WifiMpdu>(bar, hdr));
}
void
@@ -756,7 +756,7 @@ BlockAckManager::GetBlockAckReqHeader(const Mac48Address& recipient, uint8_t tid
}
void
BlockAckManager::ScheduleBar(Ptr<const WifiMpdu> bar, bool skipIfNoDataQueued)
BlockAckManager::ScheduleBar(Ptr<WifiMpdu> bar)
{
NS_LOG_FUNCTION(this << *bar);
NS_ASSERT(bar->GetHeader().IsBlockAckReq());
@@ -765,33 +765,31 @@ BlockAckManager::ScheduleBar(Ptr<const WifiMpdu> bar, bool skipIfNoDataQueued)
bar->GetPacket()->PeekHeader(reqHdr);
uint8_t tid = reqHdr.GetTidInfo();
Bar request(bar, tid, skipIfNoDataQueued);
WifiContainerQueueId queueId(WIFI_CTL_QUEUE, bar->GetHeader().GetAddr2(), std::nullopt);
Ptr<WifiMpdu> item = nullptr;
// if a BAR for the given agreement is present, replace it with the new one
std::list<Bar>::const_iterator i = m_bars.end();
for (i = m_bars.begin(); i != m_bars.end(); i++)
while ((item = m_queue->PeekByQueueId(queueId, item)))
{
if (i->bar->GetHeader().IsBlockAckReq() &&
i->bar->GetHeader().GetAddr1() == bar->GetHeader().GetAddr1() && i->tid == tid)
if (item->GetHeader().IsBlockAckReq() &&
item->GetHeader().GetAddr1() == bar->GetHeader().GetAddr1())
{
i = m_bars.erase(i);
break;
CtrlBAckRequestHeader otherHdr;
item->GetPacket()->PeekHeader(otherHdr);
if (otherHdr.GetTidInfo() == tid)
{
// replace item with bar
m_queue->Replace(item, bar);
return;
}
}
}
if (bar->GetHeader().IsRetry())
{
m_bars.push_front(request);
}
else
{
m_bars.insert(i, request);
}
m_queue->Enqueue(bar);
}
void
BlockAckManager::ScheduleMuBar(Ptr<const WifiMpdu> muBar)
BlockAckManager::ScheduleMuBar(Ptr<WifiMpdu> muBar)
{
NS_LOG_FUNCTION(this << *muBar);
NS_ASSERT(muBar->GetHeader().IsTrigger());
@@ -802,18 +800,35 @@ BlockAckManager::ScheduleMuBar(Ptr<const WifiMpdu> muBar)
NS_ASSERT(triggerHdr.IsMuBar());
#endif
Bar request(muBar, 0, false);
m_queue->Enqueue(muBar);
}
if (muBar->GetHeader().IsRetry())
const std::list<BlockAckManager::AgreementKey>&
BlockAckManager::GetSendBarIfDataQueuedList() const
{
return m_sendBarIfDataQueued;
}
void
BlockAckManager::AddToSendBarIfDataQueuedList(const Mac48Address& recipient, uint8_t tid)
{
NS_LOG_FUNCTION(this << recipient << tid);
// do nothing if the given pair is already in the list
if (std::find(m_sendBarIfDataQueued.begin(),
m_sendBarIfDataQueued.end(),
BlockAckManager::AgreementKey{recipient, tid}) == m_sendBarIfDataQueued.end())
{
m_bars.push_front(request);
}
else
{
m_bars.push_back(request);
m_sendBarIfDataQueued.emplace_back(recipient, tid);
}
}
void
BlockAckManager::RemoveFromSendBarIfDataQueuedList(const Mac48Address& recipient, uint8_t tid)
{
NS_LOG_FUNCTION(this << recipient << tid);
m_sendBarIfDataQueued.remove({recipient, tid});
}
void
BlockAckManager::InactivityTimeout(const Mac48Address& recipient, uint8_t tid)
{

View File

@@ -452,14 +452,13 @@ class BlockAckManager : public Object
/**
* \param bar the BlockAckRequest to enqueue
* \param skipIfNoDataQueued do not send if there is no data queued
*
* Enqueue the given BlockAckRequest into the queue storing the next (MU-)BAR
* frames to transmit. If a BAR for the same recipient and TID is already present
* in the queue, it is replaced by the new one. If the given BAR is retransmitted,
* it is placed at the head of the queue, otherwise at the tail.
*/
void ScheduleBar(Ptr<const WifiMpdu> bar, bool skipIfNoDataQueued = false);
void ScheduleBar(Ptr<WifiMpdu> bar);
/**
* \param muBar the MU-BAR Trigger Frame to enqueue
*
@@ -467,7 +466,32 @@ class BlockAckManager : public Object
* frames to transmit. If the given MU-BAR Trigger Frame is retransmitted,
* it is placed at the head of the queue, otherwise at the tail.
*/
void ScheduleMuBar(Ptr<const WifiMpdu> muBar);
void ScheduleMuBar(Ptr<WifiMpdu> muBar);
/// agreement key typedef (MAC address and TID)
using AgreementKey = std::pair<Mac48Address, uint8_t>;
/**
* \return the list of BA agreements (identified by the recipient and TID pair) for which a BAR
* shall only be sent if there are queued data frames belonging to those agreements
*/
const std::list<AgreementKey>& GetSendBarIfDataQueuedList() const;
/**
* Add the given (recipient, TID) pair to the list of BA agreements for which a BAR
* shall only be sent if there are queued data frames belonging to those agreements
*
* \param recipient the recipient
* \param tid the TID
*/
void AddToSendBarIfDataQueuedList(const Mac48Address& recipient, uint8_t tid);
/**
* Remove the given (recipient, TID) pair from the list of BA agreements for which a BAR
* shall only be sent if there are queued data frames belonging to those agreements
*
* \param recipient the recipient
* \param tid the TID
*/
void RemoveFromSendBarIfDataQueuedList(const Mac48Address& recipient, uint8_t tid);
protected:
void DoDispose() override;
@@ -489,9 +513,6 @@ class BlockAckManager : public Object
*/
typedef std::list<Ptr<WifiMpdu>>::iterator PacketQueueI;
/// agreement key typedef (MAC address and TID)
using AgreementKey = std::pair<Mac48Address, uint8_t>;
/// AgreementKey-indexed map of originator block ack agreements
using OriginatorAgreements =
std::map<AgreementKey, std::pair<OriginatorBlockAckAgreement, PacketQueue>>;
@@ -531,7 +552,9 @@ class BlockAckManager : public Object
OriginatorAgreements m_originatorAgreements;
RecipientAgreements m_recipientAgreements; //!< Recipient Block Ack agreements
std::list<Bar> m_bars; ///< list of BARs
std::list<AgreementKey> m_sendBarIfDataQueued; ///< list of BA agreements for which a BAR shall
///< only be sent if data is queued
std::list<Bar> m_bars; ///< list of BARs
std::map<AcIndex, Ptr<BlockAckManager>> m_bamMap; ///< AC-indexed map of all Block Ack Managers
uint8_t m_blockAckThreshold; ///< block ack threshold

View File

@@ -123,7 +123,7 @@ HeFrameExchangeManager::StartFrameExchange(Ptr<QosTxop> edca, Time availableTime
* or the next frame in the AC queue is a non-broadcast QoS data frame addressed to
* a receiver with which a BA agreement has been already established
*/
if (m_muScheduler && !edca->GetBaManager()->GetBar(false) &&
if (m_muScheduler && !GetBar(edca->GetAccessCategory()) &&
(!(mpdu = edca->PeekNextMpdu(m_linkId)) ||
(mpdu->GetHeader().IsQosData() && !mpdu->GetHeader().GetAddr1().IsGroup() &&
m_mac->GetBaAgreementEstablishedAsOriginator(mpdu->GetHeader().GetAddr1(),
@@ -168,29 +168,20 @@ HeFrameExchangeManager::StartFrameExchange(Ptr<QosTxop> edca, Time availableTime
}
bool
HeFrameExchangeManager::SendMpduFromBaManager(Ptr<QosTxop> edca,
HeFrameExchangeManager::SendMpduFromBaManager(Ptr<WifiMpdu> mpdu,
Time availableTime,
bool initialFrame)
{
NS_LOG_FUNCTION(this << edca << availableTime << initialFrame);
NS_LOG_FUNCTION(this << *mpdu << availableTime << initialFrame);
// First, check if there is a BAR to be transmitted
Ptr<const WifiMpdu> peekedItem = edca->GetBaManager()->GetBar(false);
if (!peekedItem)
{
NS_LOG_DEBUG("Block Ack Manager returned no frame to send");
return false;
}
if (peekedItem->GetHeader().IsBlockAckReq())
// First, check if there is a Trigger Frame to be transmitted
if (!mpdu->GetHeader().IsTrigger())
{
// BlockAckReq are handled by the HT FEM
return HtFrameExchangeManager::SendMpduFromBaManager(edca, availableTime, initialFrame);
return HtFrameExchangeManager::SendMpduFromBaManager(mpdu, availableTime, initialFrame);
}
NS_ASSERT(peekedItem->GetHeader().IsTrigger());
m_triggerFrame = Copy(edca->GetBaManager()->GetBar());
m_triggerFrame = mpdu;
SendPsduMap();
return true;
@@ -1030,7 +1021,12 @@ HeFrameExchangeManager::BlockAcksInTbPpduTimeout(
resetCw = true;
}
m_triggerFrame = nullptr; // this is strictly needed for DL_MU_TF_MU_BAR only
if (m_triggerFrame)
{
// this is strictly needed for DL_MU_TF_MU_BAR only
DequeueMpdu(m_triggerFrame);
m_triggerFrame = nullptr;
}
for (const auto& sta : *staMissedBlockAckFrom)
{
@@ -1409,21 +1405,18 @@ HeFrameExchangeManager::ReceiveBasicTrigger(const CtrlTriggerHeader& trigger,
txParams.m_txVector = tbTxVector;
// first, check if there is a pending BlockAckReq frame
if (Ptr<const WifiMpdu> mpdu;
(mpdu = edca->GetBaManager()->GetBar(false, tid, hdr.GetAddr2())) &&
TryAddMpdu(mpdu, txParams, ppduDuration))
if (auto mpdu = GetBar(edca->GetAccessCategory(), tid, hdr.GetAddr2());
mpdu && TryAddMpdu(mpdu, txParams, ppduDuration))
{
NS_LOG_DEBUG("Sending a BAR within a TB PPDU");
psdu = Create<WifiPsdu>(edca->GetBaManager()->GetBar(true, tid, hdr.GetAddr2()), true);
psdu = Create<WifiPsdu>(mpdu, true);
break;
}
// otherwise, check if a suitable data frame is available
if (Ptr<WifiMpdu> mpdu; (mpdu = edca->PeekNextMpdu(m_linkId, tid, hdr.GetAddr2())))
if (auto mpdu = edca->PeekNextMpdu(m_linkId, tid, hdr.GetAddr2()))
{
Ptr<WifiMpdu> item = edca->GetNextMpdu(m_linkId, mpdu, txParams, ppduDuration, false);
if (item)
if (auto item = edca->GetNextMpdu(m_linkId, mpdu, txParams, ppduDuration, false))
{
// try A-MPDU aggregation
std::vector<Ptr<WifiMpdu>> mpduList =
@@ -1782,7 +1775,12 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
// we do not expect any other BlockAck frame
m_txTimer.Cancel();
m_channelAccessManager->NotifyAckTimeoutResetNow();
m_triggerFrame = nullptr; // this is strictly needed for DL_MU_TF_MU_BAR only
if (m_triggerFrame)
{
// this is strictly needed for DL_MU_TF_MU_BAR only
DequeueMpdu(m_triggerFrame);
m_triggerFrame = nullptr;
}
m_edca->ResetCw(m_linkId);
m_psduMap.clear();
@@ -1875,6 +1873,14 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
// cancel the timer
m_txTimer.Cancel();
m_channelAccessManager->NotifyAckTimeoutResetNow();
// dequeue BlockAckReq frames included in acknowledged TB PPDUs (if any)
for (const auto& [staId, psdu] : m_psduMap)
{
if (psdu->GetNMpdus() == 1 && psdu->GetHeader(0).IsBlockAckReq())
{
DequeuePsdu(psdu);
}
}
m_psduMap.clear();
}
else if (hdr.IsBlockAck() && m_txTimer.IsRunning() &&

View File

@@ -107,7 +107,7 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager
Time GetTxDuration(uint32_t ppduPayloadSize,
Mac48Address receiver,
const WifiTxParameters& txParams) const override;
bool SendMpduFromBaManager(Ptr<QosTxop> edca, Time availableTime, bool initialFrame) override;
bool SendMpduFromBaManager(Ptr<WifiMpdu> mpdu, Time availableTime, bool initialFrame) override;
void NormalAckTimeout(Ptr<WifiMpdu> mpdu, const WifiTxVector& txVector) override;
void BlockAckTimeout(Ptr<WifiPsdu> psdu, const WifiTxVector& txVector) override;
void CtsTimeout(Ptr<WifiMpdu> rts, const WifiTxVector& txVector) override;

View File

@@ -350,7 +350,8 @@ HtFrameExchangeManager::StartFrameExchange(Ptr<QosTxop> edca, Time availableTime
NS_LOG_FUNCTION(this << edca << availableTime << initialFrame);
// First, check if there is a BAR to be transmitted
if (SendMpduFromBaManager(edca, availableTime, initialFrame))
if (auto mpdu = GetBar(edca->GetAccessCategory());
mpdu && SendMpduFromBaManager(mpdu, availableTime, initialFrame))
{
return true;
}
@@ -402,33 +403,110 @@ HtFrameExchangeManager::StartFrameExchange(Ptr<QosTxop> edca, Time availableTime
return QosFrameExchangeManager::StartFrameExchange(edca, availableTime, initialFrame);
}
Ptr<WifiMpdu>
HtFrameExchangeManager::GetBar(AcIndex ac,
std::optional<uint8_t> optTid,
std::optional<Mac48Address> optAddress)
{
NS_LOG_FUNCTION(this << +ac << optTid.has_value() << optAddress.has_value());
NS_ASSERT_MSG(optTid.has_value() == optAddress.has_value(),
"Either both or none of TID and address must be provided");
// remove all expired MPDUs from the MAC queue, so that
// BlockAckRequest frames (if needed) are scheduled
auto queue = m_mac->GetTxopQueue(ac);
queue->WipeAllExpiredMpdus();
WifiContainerQueueId queueId(WIFI_CTL_QUEUE, m_self, std::nullopt);
Ptr<WifiMpdu> bar;
Ptr<WifiMpdu> prevBar;
while ((bar = queue->PeekByQueueId(queueId, prevBar)))
{
if (bar->GetHeader().IsBlockAckReq())
{
CtrlBAckRequestHeader reqHdr;
bar->GetPacket()->PeekHeader(reqHdr);
auto tid = reqHdr.GetTidInfo();
Mac48Address recipient = bar->GetHeader().GetAddr1();
if (optAddress && (optAddress != recipient || optTid != tid))
{
NS_LOG_DEBUG("BAR " << *bar
<< " cannot be returned because it is not addressed"
" to the given station for the given TID");
prevBar = bar;
continue;
}
auto agreement = m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid);
if (!agreement)
{
NS_LOG_DEBUG("BA agreement with " << recipient << " for TID=" << +tid
<< " was torn down");
queue->Remove(bar);
continue;
}
// update BAR if the starting sequence number changed
if (auto seqNo = agreement->get().GetStartingSequence();
reqHdr.GetStartingSequence() != seqNo)
{
reqHdr.SetStartingSequence(seqNo);
Ptr<Packet> packet = Create<Packet>();
packet->AddHeader(reqHdr);
auto updatedBar = Create<WifiMpdu>(packet, bar->GetHeader());
queue->Replace(bar, updatedBar);
bar = updatedBar;
}
return bar;
}
if (bar->GetHeader().IsTrigger() && !optAddress)
{
return bar;
}
// not a BAR nor a Trigger Frame, continue
prevBar = bar;
}
// check if we can send a BAR to a recipient for which a BAR can only be sent if data queued
auto baManager = m_mac->GetQosTxop(ac)->GetBaManager();
for (const auto& [recipient, tid] : baManager->GetSendBarIfDataQueuedList())
{
if (queue->PeekByTidAndAddress(tid, recipient))
{
auto bar = m_mac->GetQosTxop(ac)->PrepareBlockAckRequest(recipient, tid);
baManager->RemoveFromSendBarIfDataQueuedList(recipient, tid);
queue->Enqueue(bar);
return bar;
}
}
return nullptr;
}
bool
HtFrameExchangeManager::SendMpduFromBaManager(Ptr<QosTxop> edca,
HtFrameExchangeManager::SendMpduFromBaManager(Ptr<WifiMpdu> mpdu,
Time availableTime,
bool initialFrame)
{
NS_LOG_FUNCTION(this << edca << availableTime << initialFrame);
NS_LOG_FUNCTION(this << *mpdu << availableTime << initialFrame);
// First, check if there is a BAR to be transmitted
Ptr<const WifiMpdu> peekedItem = edca->GetBaManager()->GetBar(false);
if (!peekedItem)
if (!mpdu->GetHeader().IsBlockAckReq())
{
NS_LOG_DEBUG("Block Ack Manager returned no frame to send");
return false;
}
NS_ASSERT(peekedItem->GetHeader().IsBlockAckReq());
// Prepare the TX parameters. Note that the default ack manager expects the
// data TxVector in the m_txVector field to compute the BlockAck TxVector.
// The m_txVector field of the TX parameters is set to the BlockAckReq TxVector
// a few lines below.
WifiTxParameters txParams;
txParams.m_txVector =
GetWifiRemoteStationManager()->GetDataTxVector(peekedItem->GetHeader(), m_allowedWidth);
GetWifiRemoteStationManager()->GetDataTxVector(mpdu->GetHeader(), m_allowedWidth);
txParams.m_protection = std::unique_ptr<WifiProtection>(new WifiNoProtection);
txParams.m_acknowledgment = GetAckManager()->TryAddMpdu(peekedItem, txParams);
txParams.m_acknowledgment = GetAckManager()->TryAddMpdu(mpdu, txParams);
NS_ABORT_IF(txParams.m_acknowledgment->method != WifiAcknowledgment::BLOCK_ACK);
@@ -437,7 +515,7 @@ HtFrameExchangeManager::SendMpduFromBaManager(Ptr<QosTxop> edca,
// the BlockAckReq frame is sent using the same TXVECTOR as the BlockAck frame
txParams.m_txVector = blockAcknowledgment->blockAckTxVector;
Time barTxDuration = m_phy->CalculateTxDuration(peekedItem->GetSize(),
Time barTxDuration = m_phy->CalculateTxDuration(mpdu->GetSize(),
blockAcknowledgment->blockAckTxVector,
m_phy->GetPhyBand());
@@ -452,8 +530,7 @@ HtFrameExchangeManager::SendMpduFromBaManager(Ptr<QosTxop> edca,
}
// we can transmit the BlockAckReq frame
Ptr<const WifiMpdu> mpdu = edca->GetBaManager()->GetBar();
SendPsduWithProtection(GetWifiPsdu(Copy(mpdu), txParams.m_txVector), txParams);
SendPsduWithProtection(GetWifiPsdu(mpdu, txParams.m_txVector), txParams);
return true;
}
@@ -622,7 +699,7 @@ HtFrameExchangeManager::TransmissionSucceeded()
{
NS_LOG_DEBUG(this);
if (m_edca && m_edca->GetTxopLimit(m_linkId).IsZero() && m_edca->GetBaManager()->GetBar(false))
if (m_edca && m_edca->GetTxopLimit(m_linkId).IsZero() && GetBar(m_edca->GetAccessCategory()))
{
// A TXOP limit of 0 indicates that the TXOP holder may transmit or cause to
// be transmitted (as responses) the following within the current TXOP:
@@ -1232,7 +1309,6 @@ HtFrameExchangeManager::MissedBlockAck(Ptr<WifiPsdu> psdu,
if (isBar)
{
psdu->GetHeader(0).SetRetry();
GetBaManager(tid)->ScheduleBar(*psdu->begin());
}
else
{
@@ -1247,11 +1323,15 @@ HtFrameExchangeManager::MissedBlockAck(Ptr<WifiPsdu> psdu,
// if a BA agreement exists, we can get here if there is no outstanding
// MPDU whose lifetime has not expired yet.
GetWifiRemoteStationManager()->ReportFinalDataFailed(*psdu->begin());
if (isBar)
{
DequeuePsdu(psdu);
}
if (m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid))
{
// schedule a BlockAckRequest with skipIfNoDataQueued set to true, so that the
// BlockAckRequest is only sent if there are data frames queued for this recipient.
GetBaManager(tid)->ScheduleBar(edca->PrepareBlockAckRequest(recipient, tid), true);
// schedule a BlockAckRequest to be sent only if there are data frames queued
// for this recipient
GetBaManager(tid)->AddToSendBarIfDataQueuedList(recipient, tid);
}
resetCw = true;
}
@@ -1397,6 +1477,11 @@ HtFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
// Reset the CW
m_edca->ResetCw(m_linkId);
// if this BlockAck was sent in response to a BlockAckReq, dequeue the blockAckReq
if (m_psdu && m_psdu->GetNMpdus() == 1 && m_psdu->GetHeader(0).IsBlockAckReq())
{
DequeuePsdu(m_psdu);
}
m_psdu = nullptr;
TransmissionSucceeded();
}

View File

@@ -166,6 +166,21 @@ class HtFrameExchangeManager : public QosFrameExchangeManager
*/
void SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOriginator);
/**
* Get the next BlockAckRequest or MU-BAR Trigger Frame to send, if any. If TID and recipient
* address are given, then only return a BlockAckRequest, if any, addressed to that recipient
* and for the given TID.
*
* \param ac the AC whose queue is searched for BlockAckRequest or Trigger Frames
* \param optTid the TID (optional)
* \param optAddress the recipient of the BAR (optional)
*
* \return the next BAR or Trigger Frame to be sent, if any
*/
Ptr<WifiMpdu> GetBar(AcIndex ac,
std::optional<uint8_t> optTid = std::nullopt,
std::optional<Mac48Address> optAddress = std::nullopt);
protected:
void DoDispose() override;
@@ -247,12 +262,11 @@ class HtFrameExchangeManager : public QosFrameExchangeManager
void DequeuePsdu(Ptr<const WifiPsdu> psdu);
/**
* If the Block Ack Manager associated with the given EDCA has a BlockAckReq frame
* to transmit (the duration of which plus the response fits within the given
* available time, if the latter is not Time::Min() and this is not the initial
* frame of a TXOP), transmit the frame and return true. Otherwise, return false.
* If the given MPDU contains a BlockAckReq frame (the duration of which plus the response
* fits within the given available time, if the latter is not Time::Min() and this is not
* the initial frame of a TXOP), transmit the frame and return true. Otherwise, return false.
*
* \param edca the EDCAF which has been granted the opportunity to transmit
* \param mpdu the given MPDU
* \param availableTime the amount of time allowed for the frame exchange. Equals
* Time::Min() in case the TXOP limit is null
* \param initialFrame true if the frame being transmitted is the initial frame
@@ -260,7 +274,7 @@ class HtFrameExchangeManager : public QosFrameExchangeManager
* limit can be exceeded
* \return true if frame is transmitted, false otherwise
*/
virtual bool SendMpduFromBaManager(Ptr<QosTxop> edca, Time availableTime, bool initialFrame);
virtual bool SendMpduFromBaManager(Ptr<WifiMpdu> mpdu, Time availableTime, bool initialFrame);
/**
* Given a non-broadcast QoS data frame, prepare the PSDU to transmit by attempting

View File

@@ -275,7 +275,7 @@ QosTxop::GetBaStartingSequence(Mac48Address address, uint8_t tid) const
return m_baManager->GetOriginatorStartingSequence(address, tid);
}
Ptr<const WifiMpdu>
Ptr<WifiMpdu>
QosTxop::PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const
{
NS_LOG_FUNCTION(this << recipient << +tid);
@@ -295,7 +295,7 @@ QosTxop::PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const
hdr.SetNoRetry();
hdr.SetNoMoreFragments();
return Create<const WifiMpdu>(bar, hdr);
return Create<WifiMpdu>(bar, hdr);
}
bool
@@ -307,16 +307,12 @@ QosTxop::UseExplicitBarAfterMissedBlockAck() const
bool
QosTxop::HasFramesToTransmit(uint8_t linkId)
{
// check if the BA manager has anything to send, so that expired
// frames (if any) are removed and a BlockAckRequest is scheduled to advance
// the starting sequence number of the transmit (and receiver) window
bool baManagerHasPackets{m_baManager->GetBar(false)};
// remove MSDUs with expired lifetime starting from the head of the queue
m_queue->WipeAllExpiredMpdus();
bool queueIsNotEmpty = (bool)(m_queue->PeekFirstAvailable(linkId, m_qosBlockedDestinations));
NS_LOG_FUNCTION(this << baManagerHasPackets << queueIsNotEmpty);
return baManagerHasPackets || queueIsNotEmpty;
NS_LOG_FUNCTION(this << queueIsNotEmpty);
return queueIsNotEmpty;
}
uint16_t

View File

@@ -144,7 +144,7 @@ class QosTxop : public Txop
* corresponding to the given TID. A block ack agreement with the given recipient
* for the given TID must have been established by such QosTxop.
*/
Ptr<const WifiMpdu> PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const;
Ptr<WifiMpdu> PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const;
/* Event handlers */
/**

View File

@@ -444,9 +444,11 @@ WifiDefaultAckManager::GetAckInfoIfBarBaSequence(Ptr<const WifiMpdu> mpdu,
}
// we get here if this is the first MPDU for this receiver
if (edca->GetBaManager()->GetBar(true, tid, receiver) ||
(acknowledgment && (!acknowledgment->stationsReplyingWithNormalAck.empty() ||
!acknowledgment->stationsReplyingWithBlockAck.empty())))
auto htFem = DynamicCast<HtFrameExchangeManager>(m_mac->GetFrameExchangeManager(m_linkId));
NS_ASSERT(htFem);
if (auto bar = htFem->GetBar(QosUtilsMapTidToAc(tid), tid, receiver);
bar || (acknowledgment && (!acknowledgment->stationsReplyingWithNormalAck.empty() ||
!acknowledgment->stationsReplyingWithBlockAck.empty())))
{
// there is a pending BlockAckReq for this receiver or another receiver
// was selected for immediate response.