wifi: (fixes #2222) Handle internal collisions

This commit is contained in:
Sébastien Deronne
2016-08-05 22:44:56 +02:00
parent 1e6e44b398
commit 07cc01d3c2
6 changed files with 169 additions and 7 deletions

View File

@@ -322,9 +322,68 @@ BlockAckManager::GetNextPacket (WifiMacHeader &hdr)
return packet;
}
Ptr<const Packet>
BlockAckManager::PeekNextPacket (WifiMacHeader &hdr)
{
NS_LOG_FUNCTION (this << &hdr);
Ptr<const Packet> packet = 0;
uint8_t tid;
Mac48Address recipient;
CleanupBuffers ();
if (!m_retryPackets.empty ())
{
NS_LOG_DEBUG ("Retry buffer size is " << m_retryPackets.size ());
std::list<PacketQueueI>::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<const Packet>
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<const Packet> packet = 0;

View File

@@ -152,6 +152,15 @@ public:
* corresponding block ack bitmap.
*/
Ptr<const Packet> 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<const Packet> 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 @@ public:
*/
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 <i>type</i> equals to <i>addr</i>, and tid equals to <i>tid</i>.
* This method doesn't remove the packet from this queue.
*/
Ptr<const Packet> PeekNextPacket (WifiMacHeader &hdr, Mac48Address recipient, uint8_t tid, Time *timestamp);
Ptr<const Packet> 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)

View File

@@ -264,7 +264,8 @@ EdcaTxopN::EdcaTxopN ()
m_mpduAggregator (0),
m_typeOfStation (STA),
m_blockAckType (COMPRESSED_BLOCK_ACK),
m_startTxop (Seconds (0))
m_startTxop (Seconds (0)),
m_isAccessRequestedForRts (false)
{
NS_LOG_FUNCTION (this);
m_transmissionListener = new EdcaTxopN::TransmissionListener (this);
@@ -483,7 +484,7 @@ uint16_t EdcaTxopN::PeekNextSequenceNumberfor (WifiMacHeader *hdr)
Ptr<const Packet>
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
@@ -496,6 +497,7 @@ void
EdcaTxopN::NotifyAccessGranted (void)
{
NS_LOG_FUNCTION (this);
m_isAccessRequestedForRts = false;
if (m_currentPacket == 0)
{
if (m_queue->IsEmpty () && !m_baManager->HasPackets ())
@@ -653,7 +655,49 @@ EdcaTxopN::NotifyAccessGranted (void)
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)
{
NS_LOG_DEBUG ("reset DCF");
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
@@ -1046,6 +1090,29 @@ EdcaTxopN::RestartAccessIfNeeded (void)
|| !m_queue->IsEmpty () || m_baManager->HasPackets ())
&& !m_dcf->IsAccessRequested ())
{
Ptr<const Packet> 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);
}
}
@@ -1058,6 +1125,29 @@ EdcaTxopN::StartAccessIfNeeded (void)
&& (!m_queue->IsEmpty () || m_baManager->HasPackets ())
&& !m_dcf->IsAccessRequested ())
{
Ptr<const Packet> 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);
}
}

View File

@@ -587,6 +587,7 @@ private:
uint16_t m_blockAckInactivityTimeout;
struct Bar m_currentBar;
Time m_startTxop;
bool m_isAccessRequestedForRts;
TracedValue<uint32_t> m_backoffTrace;
TracedValue<uint32_t> m_cwTrace;
};

View File

@@ -833,7 +833,6 @@ public:
*/
void FlushAggregateQueue (void);
protected:
/**
* Return a TXVECTOR for the DATA frame given the destination.
* The function consults WifiRemoteStationManager, which controls the rate
@@ -844,6 +843,7 @@ protected:
* \return TXVECTOR for the given packet
*/
virtual WifiTxVector GetDataTxVector (Ptr<const Packet> packet, const WifiMacHeader *hdr) const;
private:
/**
* Cancel all scheduled events. Called before beginning a transmission