From 9177900cde52fa8cb359bfdbb569946bc9c1e6bc Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Mon, 30 Nov 2020 13:03:20 +0100 Subject: [PATCH] wifi: Add a new GetNextAmsdu method to MsduAggregator which does not dequeue MSDUs. --- src/wifi/model/msdu-aggregator.cc | 70 +++++++++++++++++++++++++++++-- src/wifi/model/msdu-aggregator.h | 39 ++++++++++++++++- src/wifi/model/qos-txop.cc | 38 +++++++++++++++-- 3 files changed, 140 insertions(+), 7 deletions(-) diff --git a/src/wifi/model/msdu-aggregator.cc b/src/wifi/model/msdu-aggregator.cc index 00e2c5c9d..51423ca45 100644 --- a/src/wifi/model/msdu-aggregator.cc +++ b/src/wifi/model/msdu-aggregator.cc @@ -23,15 +23,14 @@ #include "ns3/packet.h" #include "msdu-aggregator.h" #include "qos-txop.h" -#include "mpdu-aggregator.h" #include "wifi-remote-station-manager.h" #include "mac-low.h" -#include "wifi-phy.h" -#include "wifi-net-device.h" #include "ht-capabilities.h" #include "regular-wifi-mac.h" #include "wifi-mac-queue.h" #include "wifi-mac-trailer.h" +#include "ht-frame-exchange-manager.h" +#include "wifi-tx-parameters.h" #include namespace ns3 { @@ -63,6 +62,7 @@ void MsduAggregator::DoDispose () { m_mac = 0; + m_htFem = 0; Object::DoDispose (); } @@ -71,6 +71,7 @@ MsduAggregator::SetWifiMac (const Ptr mac) { NS_LOG_FUNCTION (this << mac); m_mac = mac; + m_htFem = DynamicCast (m_mac->GetFrameExchangeManager ()); } uint16_t @@ -184,6 +185,69 @@ MsduAggregator::GetNextAmsdu (Mac48Address recipient, uint8_t tid, return amsdu; } +Ptr +MsduAggregator::GetNextAmsdu (Ptr peekedItem, WifiTxParameters& txParams, + Time availableTime, WifiMacQueueItem::QueueIteratorPair& queueIt) const +{ + NS_LOG_FUNCTION (this << *peekedItem << &txParams << availableTime); + + NS_ASSERT (peekedItem->IsQueued ()); + NS_ASSERT (peekedItem->GetQueueIteratorPairs ().size () == 1); + WifiMacQueueItem::QueueIteratorPair peekedIt = peekedItem->GetQueueIteratorPairs ().front (); + NS_ASSERT ((*peekedIt.it)->GetPacket () == peekedItem->GetPacket ()); + + uint8_t tid = peekedItem->GetHeader ().GetQosTid (); + Mac48Address recipient = peekedItem->GetHeader ().GetAddr1 (); + + /* "The Address 1 field of an MPDU carrying an A-MSDU shall be set to an + * individual address or to the GCR concealment address" (Section 10.12 + * of 802.11-2016) + */ + NS_ABORT_MSG_IF (recipient.IsBroadcast (), "Recipient address is broadcast"); + + /* "A STA shall not transmit an A-MSDU within a QoS Data frame under a block + * ack agreement unless the recipient indicates support for A-MSDU by setting + * the A-MSDU Supported field to 1 in its BlockAck Parameter Set field of the + * ADDBA Response frame" (Section 10.12 of 802.11-2016) + */ + // No check required for now, as we always set the A-MSDU Supported field to 1 + + // TODO Add support for the Max Number Of MSDUs In A-MSDU field in the Extended + // Capabilities element sent by the recipient + + NS_ASSERT (m_htFem != 0); + + if (GetMaxAmsduSize (recipient, tid, txParams.m_txVector.GetModulationClass ()) == 0) + { + NS_LOG_DEBUG ("A-MSDU aggregation disabled"); + return nullptr; + } + + Ptr amsdu = Copy (peekedItem); + uint8_t nMsdu = 1; + + peekedIt.it++; + + while ((peekedIt.it = peekedIt.queue->PeekByTidAndAddress (tid, recipient, peekedIt.it)) != peekedIt.queue->end () + && m_htFem->TryAggregateMsdu (*peekedIt.it, txParams, availableTime)) + { + amsdu->Aggregate (*peekedIt.it); + peekedIt.it++; + nMsdu++; + } + + if (nMsdu == 1) + { + NS_LOG_DEBUG ("Aggregation failed (could not aggregate at least two MSDUs)"); + return nullptr; + } + + // Aggregation succeeded + queueIt = peekedIt; + + return amsdu; +} + uint8_t MsduAggregator::CalculatePadding (uint16_t amsduSize) { diff --git a/src/wifi/model/msdu-aggregator.h b/src/wifi/model/msdu-aggregator.h index d4cc5b090..c1f8c4a69 100644 --- a/src/wifi/model/msdu-aggregator.h +++ b/src/wifi/model/msdu-aggregator.h @@ -34,6 +34,8 @@ class Packet; class QosTxop; class WifiTxVector; class RegularWifiMac; +class HtFrameExchangeManager; +class WifiTxParameters; /** * \brief Aggregator used to construct A-MSDUs @@ -98,6 +100,40 @@ public: WifiTxVector txVector, uint32_t ampduSize = 0, Time ppduDurationLimit = Time::Min ()) const; + /** + * Attempt to aggregate other MSDUs to the given A-MSDU while meeting the + * following constraints: + * + * - the A-MSDU size does not exceed the maximum A-MSDU size as determined for + * the modulation class indicated by the given TxVector + * + * - the size of the A-MPDU resulting from the aggregation of the MPDU in which + * the A-MSDU will be embedded and the current A-MPDU (as specified by the given + * TX parameters) does not exceed the maximum A-MPDU size as determined for + * the modulation class indicated by the given TxVector + * + * - the time to transmit the resulting PPDU, according to the given TxVector, + * does not exceed the maximum PPDU duration allowed by the corresponding + * modulation class (if any) + * + * - the time to transmit the resulting PPDU and to carry out protection and + * acknowledgment, as specified by the given TX parameters, does not exceed the + * given available time (if distinct from Time::Min ()) + * + * If it is not possible to aggregate at least two MSDUs, no MSDU is dequeued + * from the EDCA queue and a null pointer is returned. + * + * \param peekedItem the MSDU which we attempt to aggregate other MSDUs to + * \param txParams the TX parameters for the current frame + * \param availableTime the time available for the frame exchange + * \param[out] queueIt a QueueIteratorPair pointing to the queue item following the + * last item used to prepare the returned A-MSDU, if any; otherwise, + * its value is unchanged + * \return the resulting A-MSDU, if aggregation is possible, a null pointer otherwise. + */ + Ptr GetNextAmsdu (Ptr peekedItem, WifiTxParameters& txParams, + Time availableTime, WifiMacQueueItem::QueueIteratorPair& queueIt) const; + /** * Determine the maximum size for an A-MSDU of the given TID that can be sent * to the given receiver when using the given modulation class. @@ -139,7 +175,8 @@ protected: virtual void DoDispose (); private: - Ptr m_mac; //!< the MAC of this station + Ptr m_mac; //!< the MAC of this station + Ptr m_htFem; //!< the HT Frame Exchange Manager of this station }; } //namespace ns3 diff --git a/src/wifi/model/qos-txop.cc b/src/wifi/model/qos-txop.cc index 6170cac27..dbcbe388c 100644 --- a/src/wifi/model/qos-txop.cc +++ b/src/wifi/model/qos-txop.cc @@ -40,7 +40,7 @@ #include "wifi-phy.h" #include "wifi-ack-policy-selector.h" #include "wifi-psdu.h" -#include "qos-frame-exchange-manager.h" +#include "ht-frame-exchange-manager.h" #include "wifi-tx-parameters.h" #undef NS_LOG_APPEND_CONTEXT @@ -593,8 +593,40 @@ QosTxop::GetNextMpdu (Ptr peekedItem, WifiTxParameters& NS_ASSERT (peekedIt.queue == PeekPointer (m_queue)); Ptr mpdu; - mpdu = *peekedIt.it; - peekedIt.it++; + // If it is a non-broadcast QoS Data frame and it is not a retransmission nor a fragment, + // attempt A-MSDU aggregation + if (peekedItem->GetHeader ().IsQosData ()) + { + uint8_t tid = peekedItem->GetHeader ().GetQosTid (); + + // we should not be asked to dequeue an MPDU that is beyond the transmit window. + // Note that PeekNextMpdu() temporarily assigns the next available sequence number + // to the peeked frame + NS_ASSERT (!GetBaAgreementEstablished (recipient, tid) + || IsInWindow (peekedItem->GetHeader ().GetSequenceNumber (), + GetBaStartingSequence (recipient, tid), + GetBaBufferSize (recipient, tid))); + + // try A-MSDU aggregation + if (m_stationManager->GetHtSupported () && !recipient.IsBroadcast () + && !peekedItem->GetHeader ().IsRetry () && !peekedItem->IsFragment ()) + { + Ptr htFem = StaticCast (m_qosFem); + mpdu = htFem->GetMsduAggregator ()->GetNextAmsdu (peekedItem, txParams, availableTime, peekedIt); + } + + if (mpdu != 0) + { + NS_LOG_DEBUG ("Prepared an MPDU containing an A-MSDU"); + } + // else aggregation was not attempted or failed + } + + if (mpdu == 0) + { + mpdu = *peekedIt.it; + peekedIt.it++; + } // Assign a sequence number if this is not a fragment nor a retransmission AssignSequenceNumber (mpdu);