From 1ef995ce3b6a439c5e45bd8903ba16fb025678a7 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Wed, 3 Apr 2019 17:14:39 +0200 Subject: [PATCH] wifi: QosTxop sends peeked non-broadcast QoS Data frames to MacLow --- src/wifi/model/mac-low.cc | 53 ++++++++++++++++++++++++---- src/wifi/model/qos-txop.cc | 71 ++++++++++++++++++++++++-------------- src/wifi/model/qos-txop.h | 26 +++++++++----- 3 files changed, 109 insertions(+), 41 deletions(-) diff --git a/src/wifi/model/mac-low.cc b/src/wifi/model/mac-low.cc index 98bb7a15c..464ed44db 100644 --- a/src/wifi/model/mac-low.cc +++ b/src/wifi/model/mac-low.cc @@ -529,15 +529,17 @@ MacLow::StartTransmission (Ptr mpdu, /* The packet received by this function can be any of the following: * (a) a management frame dequeued from the Txop * (b) a non-QoS data frame dequeued from the Txop - * (c) a QoS data or DELBA Request frame dequeued from a QosTxop - * (d) a BlockAckReq or ADDBA Request frame + * (c) a non-broadcast QoS Data frame peeked or dequeued from a QosTxop + * (d) a broadcast QoS data or DELBA Request frame dequeued from a QosTxop + * (e) a BlockAckReq or ADDBA Request frame + * (f) a fragment of non-QoS/QoS Data frame dequeued from the Txop/QosTxop */ - if (hdr.IsQosData () && !hdr.GetAddr1 ().IsBroadcast ()) + if (hdr.IsQosData () && !hdr.GetAddr1 ().IsBroadcast () + && !hdr.IsMoreFragments () && hdr.GetFragmentNumber () == 0) { // We get here if the received packet is a non-broadcast QoS data frame - uint8_t tid = GetTid (mpdu->GetPacket (), hdr); + uint8_t tid = hdr.GetQosTid (); Ptr qosTxop = m_edca.find (QosUtilsMapTidToAc (tid))->second; - std::vector> mpduList; // if a TXOP limit exists, compute the remaining TXOP duration Time txopLimit = Seconds (0); @@ -547,10 +549,43 @@ MacLow::StartTransmission (Ptr mpdu, NS_ASSERT (txopLimit.IsPositive ()); } + // QosTxop may send us a peeked frame + Ptr tmp = qosTxop->PeekNextFrame (); + bool isPeeked = (tmp != 0 && tmp->GetPacket () == mpdu->GetPacket ()); + + Ptr newMpdu; + // If the frame has been peeked, dequeue it if it meets the size and duration constraints + if (isPeeked) + { + newMpdu = qosTxop->DequeuePeekedFrame (mpdu, m_currentTxVector, true, 0, txopLimit); + } + else if (IsWithinSizeAndTimeLimits (mpdu, m_currentTxVector, 0, txopLimit)) + { + newMpdu = mpdu; + } + + if (newMpdu == 0) + { + // if the frame has been dequeued, then there is no BA agreement with the + // receiver (otherwise the frame would have been peeked). Hence, the frame + // has been sent under Normal Ack policy, not acknowledged and now retransmitted. + // If we cannot send it now, let the QosTxop retransmit it again. + // If the frame has been just peeked, reset the current packet at QosTxop. + if (isPeeked) + { + qosTxop->UpdateCurrentPacket (Create (nullptr, WifiMacHeader ())); + } + return; + } + // Update the current packet at QosTxop, given that A-MSDU aggregation may have + // been performed on the peeked frame + qosTxop->UpdateCurrentPacket (newMpdu); + //Perform MPDU aggregation if possible + std::vector> mpduList; if (m_mpduAggregator != 0) { - mpduList = m_mpduAggregator->GetNextAmpdu (mpdu, m_currentTxVector, txopLimit); + mpduList = m_mpduAggregator->GetNextAmpdu (newMpdu, m_currentTxVector, txopLimit); } if (mpduList.size () > 1) @@ -564,11 +599,15 @@ MacLow::StartTransmission (Ptr mpdu, || m_currentTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HE) { // VHT/HE single MPDU - m_currentPacket = Create (mpdu, true); + m_currentPacket = Create (newMpdu, true); NS_LOG_DEBUG ("tx unicast S-MPDU with sequence number " << hdr.GetSequenceNumber ()); qosTxop->SetAmpduExist (hdr.GetAddr1 (), true); } + else // HT + { + m_currentPacket = Create (newMpdu, false); + } // A QoS Txop must have an installed ack policy selector NS_ASSERT (qosTxop->GetAckPolicySelector () != 0); diff --git a/src/wifi/model/qos-txop.cc b/src/wifi/model/qos-txop.cc index 9ea010259..98c55665f 100644 --- a/src/wifi/model/qos-txop.cc +++ b/src/wifi/model/qos-txop.cc @@ -459,6 +459,15 @@ QosTxop::GetTransmissionParameters (Ptr frame) const return params; } +void +QosTxop::UpdateCurrentPacket (Ptr mpdu) +{ + NS_LOG_FUNCTION (this << *mpdu); + m_currentPacket = mpdu->GetPacket (); + m_currentHdr = mpdu->GetHeader (); + m_currentPacketTimestamp = mpdu->GetTimeStamp (); +} + void QosTxop::NotifyAccessGranted (void) { @@ -506,18 +515,31 @@ QosTxop::NotifyAccessGranted (void) } m_stationManager->UpdateFragmentationThreshold (); - Time ppduDurationLimit = Seconds (0); - - // compute the limit on the PPDU duration due to the TXOP duration, if any - if (peekedItem->GetHeader ().IsQosData () && GetTxopLimit ().IsStrictlyPositive ()) + Ptr item; + // non-broadcast QoS data frames may be sent in MU PPDUs. Given that at this stage + // we do not know the bandwidth it would be given nor the selected acknowledgment + // sequence, we cannot determine the constraints on size and duration limit. Hence, + // we only peek the non-broadcast QoS data frame. MacLow will be in charge of + // computing the correct limits and dequeue the frame. + if (peekedItem->GetHeader ().IsQosData () && !peekedItem->GetHeader ().GetAddr1 ().IsBroadcast () + && !NeedFragmentation ()) { - MacLowTransmissionParameters params = GetTransmissionParameters (peekedItem); - ppduDurationLimit = GetTxopRemaining () - m_low->CalculateOverheadTxTime (peekedItem, params); + item = Copy (peekedItem); } + else + { + // compute the limit on the PPDU duration due to the TXOP duration, if any + Time ppduDurationLimit = Seconds (0); + if (peekedItem->GetHeader ().IsQosData () && GetTxopLimit ().IsStrictlyPositive ()) + { + MacLowTransmissionParameters params = GetTransmissionParameters (peekedItem); + ppduDurationLimit = GetTxopRemaining () - m_low->CalculateOverheadTxTime (peekedItem, params); + } - // dequeue the peeked item if it fits within the TXOP duration, if any - Ptr item = DequeuePeekedFrame (peekedItem, m_low->GetDataTxVector (peekedItem), - !NeedFragmentation (), 0, ppduDurationLimit); + // dequeue the peeked item if it fits within the TXOP duration, if any + item = DequeuePeekedFrame (peekedItem, m_low->GetDataTxVector (peekedItem), + !NeedFragmentation (), 0, ppduDurationLimit); + } if (item == 0) { @@ -549,15 +571,6 @@ QosTxop::NotifyAccessGranted (void) { m_currentParams = GetTransmissionParameters (mpdu); - // check if the current frame meets the QoS TXOP Limit, if any - if (mpdu->GetHeader ().IsQosData () && GetTxopLimit ().IsStrictlyPositive () && - m_low->CalculateOverallTxTime (mpdu->GetPacket (), &mpdu->GetHeader (), - m_currentParams) > GetTxopRemaining ()) - { - NS_LOG_DEBUG ("Not enough time in the current TXOP"); - return; - } - //With COMPRESSED_BLOCK_ACK fragmentation must be avoided. if (((m_currentHdr.IsQosData () && !m_currentHdr.IsQosAmsdu ()) || (m_currentHdr.IsData () && !m_currentHdr.IsQosData ())) @@ -1080,14 +1093,22 @@ QosTxop::StartNextPacket (void) return; } - // when dequeuing the peeked packet, A-MSDU aggregation is attempted if the - // packet has been peeked from the EDCA queue. Thus, compute the max available - // time for the transmission of the PPDU - Time maxPpduDuration = GetTxopRemaining () - m_low->CalculateOverheadTxTime (nextFrame, params); - NS_ASSERT (maxPpduDuration.IsPositive ()); + Ptr item; + // non-broadcast QoS data frames may be sent in MU PPDUs. Given that at this stage + // we do not know the bandwidth it would be given nor the selected acknowledgment + // sequence, we cannot determine the constraints on size and duration limit. Hence, + // we only peek the non-broadcast QoS data frame. MacLow will be in charge of + // computing the correct limits and dequeue the frame. + if (nextFrame->GetHeader ().IsQosData () && !nextFrame->GetHeader ().GetAddr1 ().IsBroadcast ()) + { + item = Create (*nextFrame); + } + else + { + // dequeue the peeked frame + item = DequeuePeekedFrame (nextFrame, m_low->GetDataTxVector (nextFrame)); + } - Ptr item = DequeuePeekedFrame (nextFrame, m_low->GetDataTxVector (nextFrame), - true, 0, maxPpduDuration); NS_ASSERT (item != 0); NS_LOG_DEBUG ("start next packet " << *item << " within the current TXOP"); m_currentPacket = item->GetPacket (); diff --git a/src/wifi/model/qos-txop.h b/src/wifi/model/qos-txop.h index c7705cfa0..4ff491142 100644 --- a/src/wifi/model/qos-txop.h +++ b/src/wifi/model/qos-txop.h @@ -423,15 +423,15 @@ public: */ Ptr PeekNextFrame (uint8_t tid = 8, Mac48Address recipient = Mac48Address::GetBroadcast ()); /** - * Dequeue the frame that has been previously peeked by calling PeekNextFrame - * or PeekNextFrameByTidAndAddress. If the peeked frame is a QoS Data frame, - * it is actually dequeued if it meets the constraint on the maximum A-MPDU - * size (by assuming that the frame has to be aggregated to an existing A-MPDU - * of the given size) and its transmission time does not exceed the given - * PPDU duration limit (if strictly positive). If the peeked frame is a unicast - * QoS Data frame stored in the EDCA queue, attempt to perform A-MSDU aggregation - * (while meeting the constraints mentioned above) if aggregate is true - * and assign a sequence number to the dequeued frame. + * Dequeue the frame that has been previously peeked by calling PeekNextFrame. + * If the peeked frame is a QoS Data frame, it is actually dequeued if it meets + * the constraint on the maximum A-MPDU size (by assuming that the frame has to + * be aggregated to an existing A-MPDU of the given size) and its transmission + * time does not exceed the given PPDU duration limit (if strictly positive). + * If the peeked frame is a unicast QoS Data frame stored in the EDCA queue, + * attempt to perform A-MSDU aggregation (while meeting the constraints mentioned + * above) if aggregate is true and assign a sequence number to the + * dequeued frame. * * \param peekedItem the peeked frame. * \param txVector the TX vector used to transmit the peeked frame @@ -452,6 +452,14 @@ public: */ MacLowTransmissionParameters GetTransmissionParameters (Ptr frame) const; + /** + * Update the current packet this QosTxop is trying to transmit. This method + * is typically called by MacLow when it changes (i.e., by performing A-MSDU + * aggregation) the packet received from this QosTxop. + * + * \param mpdu the MPDU that MacLow is forwarding down to the PHY. + */ + void UpdateCurrentPacket (Ptr mpdu); /** * The packet we sent was successfully received by the receiver. *