--- a/src/wifi/model/block-ack-manager.cc Mon Jun 13 22:11:06 2016 +0200 +++ a/src/wifi/model/block-ack-manager.cc Tue Jun 14 21:15:52 2016 +0200 @@ -322,9 +322,68 @@ return packet; } +Ptr +BlockAckManager::PeekNextPacket (WifiMacHeader &hdr) +{ + NS_LOG_FUNCTION (this << &hdr); + Ptr packet = 0; + uint8_t tid; + Mac48Address recipient; + CleanupBuffers (); + if (!m_retryPackets.empty ()) + { + NS_LOG_DEBUG ("Retry buffer size is " << m_retryPackets.size ()); + std::list::iterator it = m_retryPackets.begin (); + while (it != m_retryPackets.end ()) + { + if ((*it)->hdr.IsQosData ()) + { + tid = (*it)->hdr.GetQosTid (); + } + else + { + NS_FATAL_ERROR ("Packet in blockAck manager retry queue is not Qos Data"); + } + recipient = (*it)->hdr.GetAddr1 (); + AgreementsI agreement = m_agreements.find (std::make_pair (recipient, tid)); + NS_ASSERT (agreement != m_agreements.end ()); + packet = (*it)->packet->Copy (); + hdr = (*it)->hdr; + hdr.SetRetry (); + if (hdr.IsQosData ()) + { + tid = hdr.GetQosTid (); + } + else + { + NS_FATAL_ERROR ("Packet in blockAck manager retry queue is not Qos Data"); + } + recipient = hdr.GetAddr1 (); + if (!agreement->second.first.IsHtSupported () + && (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED) + || SwitchToBlockAckIfNeeded (recipient, tid, hdr.GetSequenceNumber ()))) + { + hdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK); + } + else + { + /* From section 9.10.3 in IEEE802.11e standard: + * In order to improve efficiency, originators using the Block Ack facility + * may send MPDU frames with the Ack Policy subfield in QoS control frames + * set to Normal Ack if only a few MPDUs are available for transmission.[...] + * When there are sufficient number of MPDUs, the originator may switch back to + * the use of Block Ack. + */ + hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK); + } + break; + } + } + return packet; +} Ptr -BlockAckManager::PeekNextPacket (WifiMacHeader &hdr, Mac48Address recipient, uint8_t tid, Time *tstamp) +BlockAckManager::PeekNextPacketByTidAndAddress (WifiMacHeader &hdr, Mac48Address recipient, uint8_t tid, Time *tstamp) { NS_LOG_FUNCTION (this); Ptr packet = 0; --- a/src/wifi/model/block-ack-manager.h Mon Jun 13 22:11:06 2016 +0200 +++ a/src/wifi/model/block-ack-manager.h Tue Jun 14 21:15:52 2016 +0200 @@ -152,6 +152,15 @@ * corresponding block ack bitmap. */ Ptr GetNextPacket (WifiMacHeader &hdr); + /** + * \param hdr 802.11 header of returned packet (if exists). + * + * \return the packet + * + * This methods returns a packet (if exists) indicated as not received in + * corresponding block ack bitmap. This method doesn't remove the packet from this queue. + */ + Ptr PeekNextPacket (WifiMacHeader &hdr); bool HasBar (struct Bar &bar); /** * Returns true if there are packets that need of retransmission or at least a @@ -320,9 +329,11 @@ */ bool RemovePacket (uint8_t tid, Mac48Address recipient, uint16_t seqnumber); /* - * Peek in retransmit queue and get the next packet without removing it from the queue + * Peek in retransmit queue and get the next packet having address indicated + * by type equals to addr, and tid equals to tid. + * This method doesn't remove the packet from this queue. */ - Ptr PeekNextPacket (WifiMacHeader &hdr, Mac48Address recipient, uint8_t tid, Time *timestamp); + Ptr PeekNextPacketByTidAndAddress (WifiMacHeader &hdr, Mac48Address recipient, uint8_t tid, Time *timestamp); /** * This function returns true if the lifetime of the packets a BAR refers to didn't expire yet else it returns false. * If it return false then the BAR will be discarded (i.e. will not be re-transmitted) --- a/src/wifi/model/edca-txop-n.cc Mon Jun 13 22:11:06 2016 +0200 +++ a/src/wifi/model/edca-txop-n.cc Tue Jun 14 21:15:52 2016 +0200 @@ -258,7 +258,8 @@ m_msduAggregator (0), m_mpduAggregator (0), m_typeOfStation (STA), - m_blockAckType (COMPRESSED_BLOCK_ACK) + m_blockAckType (COMPRESSED_BLOCK_ACK), + m_isAccessRequestedForRts (false) { NS_LOG_FUNCTION (this); m_transmissionListener = new EdcaTxopN::TransmissionListener (this); @@ -464,7 +465,7 @@ Ptr EdcaTxopN::PeekNextRetransmitPacket (WifiMacHeader &header,Mac48Address recipient, uint8_t tid, Time *timestamp) { - return m_baManager->PeekNextPacket (header,recipient,tid, timestamp); + return m_baManager->PeekNextPacketByTidAndAddress (header,recipient,tid, timestamp); } void @@ -477,6 +478,7 @@ EdcaTxopN::NotifyAccessGranted (void) { NS_LOG_FUNCTION (this); + m_isAccessRequestedForRts = false; if (m_currentPacket == 0) { if (m_queue->IsEmpty () && !m_baManager->HasPackets ()) @@ -633,7 +635,48 @@ void EdcaTxopN::NotifyInternalCollision (void) { NS_LOG_FUNCTION (this); - NotifyCollision (); + bool resetDcf = false; + if (m_isAccessRequestedForRts) + { + if (!NeedRtsRetransmission ()) + { + resetDcf = true; + m_stationManager->ReportFinalRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr); + } + else + { + m_stationManager->ReportRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr); + } + } + else + { + if (!NeedDataRetransmission ()) + { + resetDcf = true; + m_stationManager->ReportFinalDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr); + } + else + { + m_stationManager->ReportDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr); + } + } + if (resetDcf) + { + if (!m_txFailedCallback.IsNull ()) + { + m_txFailedCallback (m_currentHdr); + } + //to reset the dcf. + m_currentPacket = 0; + m_dcf->ResetCw (); + } + else + { + m_dcf->UpdateFailedCw (); + } + m_backoffTrace = m_rng->GetNext (0, m_dcf->GetCw ()); + m_dcf->StartBackoffNow (m_backoffTrace); + RestartAccessIfNeeded (); } void @@ -1024,6 +1067,29 @@ || !m_queue->IsEmpty () || m_baManager->HasPackets ()) && !m_dcf->IsAccessRequested ()) { + Ptr packet; + WifiMacHeader hdr; + if (m_currentPacket != 0) + { + packet = m_currentPacket; + hdr = m_currentHdr; + } + else if (m_baManager->HasPackets ()) + { + packet = m_baManager->PeekNextPacket (hdr); + } + else if (m_queue->PeekFirstAvailable (&hdr, m_currentPacketTimestamp, m_qosBlockedDestinations) != 0) + { + packet = m_queue->PeekFirstAvailable (&hdr, m_currentPacketTimestamp, m_qosBlockedDestinations); + } + if (packet != 0) + { + m_isAccessRequestedForRts = m_stationManager->NeedRts (hdr.GetAddr1 (), &hdr, packet, m_low->GetDataTxVector (packet, &hdr)); + } + else + { + m_isAccessRequestedForRts = false; + } m_manager->RequestAccess (m_dcf); } } @@ -1036,6 +1102,29 @@ && (!m_queue->IsEmpty () || m_baManager->HasPackets ()) && !m_dcf->IsAccessRequested ()) { + Ptr packet; + WifiMacHeader hdr; + if (m_currentPacket != 0) + { + packet = m_currentPacket; + hdr = m_currentHdr; + } + else if (m_baManager->HasPackets ()) + { + packet = m_baManager->PeekNextPacket (hdr); + } + else if (m_queue->PeekFirstAvailable (&hdr, m_currentPacketTimestamp, m_qosBlockedDestinations) != 0) + { + packet = m_queue->PeekFirstAvailable (&hdr, m_currentPacketTimestamp, m_qosBlockedDestinations); + } + if (packet != 0) + { + m_isAccessRequestedForRts = m_stationManager->NeedRts (hdr.GetAddr1 (), &hdr, packet, m_low->GetDataTxVector (packet, &hdr)); + } + else + { + m_isAccessRequestedForRts = false; + } m_manager->RequestAccess (m_dcf); } } --- a/src/wifi/model/edca-txop-n.h Mon Jun 13 22:11:06 2016 +0200 +++ a/src/wifi/model/edca-txop-n.h Tue Jun 14 21:15:52 2016 +0200 @@ -567,6 +567,7 @@ Time m_currentPacketTimestamp; uint16_t m_blockAckInactivityTimeout; struct Bar m_currentBar; + bool m_isAccessRequestedForRts; TracedValue m_backoffTrace; TracedValue m_cwTrace; }; --- a/src/wifi/model/mac-low.h Mon Jun 13 22:11:06 2016 +0200 +++ a/src/wifi/model/mac-low.h Tue Jun 14 21:15:52 2016 +0200 @@ -823,7 +823,6 @@ */ void FlushAggregateQueue (void); -protected: /** * Return a TXVECTOR for the DATA frame given the destination. * The function consults WifiRemoteStationManager, which controls the rate @@ -834,6 +833,7 @@ * \return TXVECTOR for the given packet */ virtual WifiTxVector GetDataTxVector (Ptr packet, const WifiMacHeader *hdr) const; + private: /** * Cancel all scheduled events. Called before beginning a transmission