I am using A-MPDU aggregation on the DL of a BSS. Every once in a while the AP needs to retransmit a frame (Retry=1). Things work fine as long as the MPDUs are transmitted individually but once they are aggregated with each other or with other new packets in an A-MPDU, then the retransmission pattern continues indefinitely. That is, all the previously retransmitted MPDUs and the new ones will get Retry=1.
I haven't found the source of the problem yet, but after digging around into the code I came across a few things that I didn't understand.
In MacLow::AggregateToAmpdu (), why is qosPolicy set to zero (i.e., Normal ACK) when we are doing A-MPDU aggregation? Shouldn't this be qosPolicy=3? Here's the piece of code I am referring to. I have marked that line with >>>> :
----------------------------------------------------
if (hdr.IsQosData() || hdr.IsBlockAck()|| hdr.IsBlockAckReq())
{
Time tstamp;
uint8_t tid = GetTid (packet, hdr);
Ptr<PerStaWifiMacQueue> queue;
AcIndex ac = QosUtilsMapTidToAc (tid);
//since a blockack agreement always preceeds mpdu aggregation there should always exist blockAck listener
std::map<AcIndex, MacLowBlockAckEventListener*>::const_iterator listenerIt= m_edcaListeners.find(ac);
NS_ASSERT (listenerIt != m_edcaListeners.end ());
queue = listenerIt->second->GetQueue()->GetObject<PerStaWifiMacQueue>();
if (!hdr.GetAddr1 ().IsBroadcast () && m_mpduAggregator!= 0)
{
//Have to make sure that their exist a block Ack agreement before sending an AMPDU (BlockAck Manager)
if (listenerIt->second->GetBlockAckAgreementExists (hdr.GetAddr1(), tid))
{
/* here is performed mpdu aggregation */
/* MSDU aggregation happened in edca if the user asked for it so m_currentPacket may contains a normal packet or a A-MSDU*/
Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
peekedHdr = hdr;
uint16_t startingSequenceNumber = 0;
uint16_t currentSequenceNumber = 0;
>>>> uint8_t qosPolicy = 0;
uint16_t blockAckSize = 0;
-------------------------------------
I have checked ans this line is always executed!
Also, in BlockAckManager::GetNextPacket (), why is the else statement always taken? Shouldn't we use BLOCK_ACK?
--------------------------------------------------
if (!agreement->second.first.IsHtSupported ()//sva why is there a ! (not) here? shouldn't it be removed?
&& (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);
AgreementsI i = m_agreements.find (std::make_pair (recipient, tid));
i->second.second.erase (*it);
}
--------------------------------------------------
I have checked and all three function calls in the if statement return true. In particular, why should we resort to NORMAL_ACK if
agreement->second.first.IsHtSupported () == true?
I would appreciate any hint.
Thanks,