wifi: (fixes #2222) Handle internal collisions
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user