diff --git a/src/wifi/model/mpdu-aggregator.cc b/src/wifi/model/mpdu-aggregator.cc index af4f05b3c..408297145 100644 --- a/src/wifi/model/mpdu-aggregator.cc +++ b/src/wifi/model/mpdu-aggregator.cc @@ -37,6 +37,7 @@ #include "regular-wifi-mac.h" #include "ctrl-headers.h" #include "wifi-mac-trailer.h" +#include "wifi-tx-parameters.h" NS_LOG_COMPONENT_DEFINE ("MpduAggregator"); @@ -302,4 +303,65 @@ MpduAggregator::GetNextAmpdu (Ptr mpdu, WifiTxVector txV return mpduList; } +std::vector> +MpduAggregator::GetNextAmpdu (Ptr mpdu, WifiTxParameters& txParams, + Time availableTime, WifiMacQueueItem::QueueIteratorPair queueIt) const +{ + NS_LOG_FUNCTION (this << *mpdu << &txParams << availableTime); + + std::vector> mpduList; + + Mac48Address recipient = mpdu->GetHeader ().GetAddr1 (); + NS_ASSERT (mpdu->GetHeader ().IsQosData () && !recipient.IsBroadcast ()); + uint8_t tid = mpdu->GetHeader ().GetQosTid (); + + Ptr qosTxop = m_mac->GetQosTxop (tid); + NS_ASSERT (qosTxop != 0); + + //Have to make sure that the block ack agreement is established and A-MPDU is enabled + if (qosTxop->GetBaAgreementEstablished (recipient, tid) + && GetMaxAmpduSize (recipient, tid, txParams.m_txVector.GetModulationClass ()) > 0) + { + /* here is performed MPDU aggregation */ + Ptr nextMpdu = mpdu; + + while (nextMpdu != 0) + { + // if we are here, nextMpdu can be aggregated to the A-MPDU. + NS_LOG_DEBUG ("Adding packet with sequence number " << nextMpdu->GetHeader ().GetSequenceNumber () + << " to A-MPDU, packet size = " << nextMpdu->GetSize () + << ", A-MPDU size = " << txParams.GetSize (recipient)); + + mpduList.push_back (nextMpdu); + + // If allowed by the BA agreement, get the next MPDU + nextMpdu = 0; + + Ptr peekedMpdu; + peekedMpdu = qosTxop->PeekNextMpdu (queueIt, tid, recipient); + if (peekedMpdu != 0) + { + // PeekNextMpdu() does not return an MPDU that is beyond the transmit window + NS_ASSERT (IsInWindow (peekedMpdu->GetHeader ().GetSequenceNumber (), + qosTxop->GetBaStartingSequence (recipient, tid), + qosTxop->GetBaBufferSize (recipient, tid))); + + // get the next MPDU to aggregate, provided that the constraints on size + // and duration limit are met. Note that the returned MPDU differs from + // the peeked MPDU if A-MSDU aggregation is enabled. + NS_LOG_DEBUG ("Trying to aggregate another MPDU"); + nextMpdu = qosTxop->GetNextMpdu (peekedMpdu, txParams, availableTime, false, queueIt); + } + } + + if (mpduList.size () == 1) + { + // return an empty vector if it was not possible to aggregate at least two MPDUs + mpduList.clear (); + } + } + + return mpduList; +} + } //namespace ns3 diff --git a/src/wifi/model/mpdu-aggregator.h b/src/wifi/model/mpdu-aggregator.h index 4b4bbd834..babfdd1be 100644 --- a/src/wifi/model/mpdu-aggregator.h +++ b/src/wifi/model/mpdu-aggregator.h @@ -34,6 +34,7 @@ class WifiTxVector; class Packet; class WifiMacQueueItem; class RegularWifiMac; +class WifiTxParameters; /** * \brief Aggregator used to construct A-MPDUs @@ -120,6 +121,44 @@ public: WifiTxVector txVector, Time ppduDurationLimit = Time::Min ()) const; + /** + * Attempt to aggregate other MPDUs to the given MPDU, while meeting the + * following constraints: + * + * - the size of the resulting A-MPDU 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 ()) + * + * For now, only non-broadcast QoS Data frames can be aggregated (do not pass + * other types of frames to this method). MPDUs to aggregate are looked for + * among those with the same TID and receiver as the given MPDU. + * + * The resulting A-MPDU is returned as a vector of the constituent MPDUs + * (including the given MPDU), which are not actually aggregated (call the + * Aggregate method afterwards to get the actual A-MPDU). If aggregation was + * not possible (aggregation is disabled, there is no Block Ack agreement + * established with the receiver, or another MPDU to aggregate was not found), + * the returned vector is empty. + * + * \param mpdu the given MPDU. + * \param txParams the TX parameters used to transmit the frame + * \param availableTime the time available for the frame exchange + * \param queueIt the QueueIteratorPair pointing to the queue item from which the + * search for an MPDU starts, if the QueueIteratorPair is valid + * \return the resulting A-MPDU, if aggregation is possible. + */ + std::vector> GetNextAmpdu (Ptr mpdu, + WifiTxParameters& txParams, + Time availableTime, + WifiMacQueueItem::QueueIteratorPair queueIt) const; + /** * Set the MAC layer to use. *