Bug 2075 [wifi] - A-MPDU using RTS/CTS behaves wrongly when MaxSsrc is reached
authorSébastien Deronne <sebastien.deronne@gmail.com>
Tue, 05 May 2015 00:29:40 +0200
changeset 11353 b03d1c0ada03
parent 11352 a1f6f647d516
child 11354 e44c24fef5fa
Bug 2075 [wifi] - A-MPDU using RTS/CTS behaves wrongly when MaxSsrc is reached
RELEASE_NOTES
src/wifi/model/edca-txop-n.cc
src/wifi/model/mac-low.cc
src/wifi/model/mac-low.h
--- a/RELEASE_NOTES	Mon May 04 23:55:32 2015 +0200
+++ b/RELEASE_NOTES	Tue May 05 00:29:40 2015 +0200
@@ -40,6 +40,7 @@
 - Bug 2066 - A-MPDU reception should check for successful preamble
 - Bug 2070 - Wrong report of Packets and Bytes stored in CoDeL
 - Bug 2073 - NDisc cache entries update timer might be stuck in a loop
+- Bug 2075 - A-MPDU using RTS/CTS behaves wrongly when MaxSsrc is reached
 - Bug 2076 - TCP MinRTO Attribute is not actually used
 - Bug 2077 - Icmpv6L4Protocol::HandleDestinationUnreachable must check the packet size, not its serialized size
 - Bug 2079 - mcs variable in ht-wifi-network example is confusing
--- a/src/wifi/model/edca-txop-n.cc	Mon May 04 23:55:32 2015 +0200
+++ b/src/wifi/model/edca-txop-n.cc	Tue May 05 00:29:40 2015 +0200
@@ -659,9 +659,35 @@
       if (GetAmpduExist())
         {
           m_low->FlushAggregateQueue ();
+          
+          NS_LOG_DEBUG ("Transmit Block Ack Request");
+          CtrlBAckRequestHeader reqHdr;
+          reqHdr.SetType (COMPRESSED_BLOCK_ACK);
+          uint8_t tid = m_currentHdr.GetQosTid ();
+          reqHdr.SetStartingSequence (m_txMiddle->PeekNextSequenceNumberfor (&m_currentHdr));
+          reqHdr.SetTidInfo (tid);
+          reqHdr.SetHtImmediateAck(true);
+          Ptr<Packet> bar = Create<Packet> ();
+          bar->AddHeader (reqHdr);
+          Bar request (bar, m_currentHdr.GetAddr1 (), tid, reqHdr.MustSendHtImmediateAck());
+          m_currentBar = request;
+          WifiMacHeader hdr;
+          hdr.SetType (WIFI_MAC_CTL_BACKREQ);
+          hdr.SetAddr1 (request.recipient);
+          hdr.SetAddr2 (m_low->GetAddress ());
+          hdr.SetAddr3 (m_low->GetBssid ());
+          hdr.SetDsNotTo ();
+          hdr.SetDsNotFrom ();
+          hdr.SetNoRetry ();
+          hdr.SetNoMoreFragments ();
+          m_currentPacket = request.bar;
+          m_currentHdr = hdr;
+        }
+      else
+        {
+          m_currentPacket = 0;
         }
       // to reset the dcf.
-      m_currentPacket = 0;
       m_dcf->ResetCw ();
     }
   else
--- a/src/wifi/model/mac-low.cc	Mon May 04 23:55:32 2015 +0200
+++ b/src/wifi/model/mac-low.cc	Tue May 05 00:29:40 2015 +0200
@@ -913,7 +913,8 @@
                                     rxSnr, txMode);
       m_stationManager->ReportDataOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
                                       rxSnr, txMode, tag.Get ());
-        
+
+      FlushAggregateQueue();
       bool gotAck = false;
       if (m_txParams.MustWaitNormalAck ()
           && m_normalAckTimeoutEvent.IsRunning ())
@@ -951,6 +952,7 @@
       m_listener->GotBlockAck (&blockAck, hdr.GetAddr2 (),txMode);
       m_sentMpdus = 0;
       m_ampdu = false;
+      FlushAggregateQueue();
     }
   else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
     {
@@ -1576,6 +1578,7 @@
   m_listener = 0;
   m_sentMpdus = 0;
   m_ampdu = false;
+  FlushAggregateQueue();
   listener->MissedAck ();
 }
 void
@@ -1606,6 +1609,7 @@
   m_listener = 0;
   m_sentMpdus = 0;
   m_ampdu = false;
+  FlushAggregateQueue();
   listener->MissedBlockAck ();
 }
 void
@@ -1992,6 +1996,19 @@
   NS_ASSERT (m_currentPacket != 0);
   WifiTxVector dataTxVector = GetDataTxVector (m_currentPacket, &m_currentHdr);
   
+  if (m_aggregateQueue->GetSize () != 0)
+  {
+    for(int i = 0; i < m_txPackets.size(); i++)
+    {
+      uint8_t tid = GetTid (m_txPackets.at(i).packet, m_txPackets.at(i).hdr);
+      AcIndex ac = QosUtilsMapTidToAc (tid);
+      std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt= m_edcaListeners.find(ac);
+      
+      listenerIt->second->CompleteMpduTx (m_txPackets.at(i).packet, m_txPackets.at(i).hdr, m_txPackets.at(i).timestamp);
+    }
+    m_txPackets.clear ();
+  }
+  
   WifiPreamble preamble;       
   if (m_phy->GetGreenfield() && m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
      //In the future has to make sure that receiver has greenfield enabled
@@ -2743,13 +2760,27 @@
                       m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
                       if (i == 1 && hdr.IsQosData ())
                       {
-                          listenerIt->second->CompleteMpduTx (packet, hdr, tstamp);
+                        if (!m_txParams.MustSendRts ())
+                        {
+                           listenerIt->second->CompleteMpduTx (packet, hdr, tstamp);
+                        }
+                        else
+                        {
+                          InsertInTxQueue (packet, hdr, tstamp);
+                        }
                       }
                       NS_LOG_DEBUG ("Adding packet with Sequence number " << peekedHdr.GetSequenceNumber()<<" to A-MPDU, packet size = " << newPacket->GetSize ()<< ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
                       i++;
                       isAmpdu = true;
                       m_sentMpdus++;
-                      listenerIt->second->CompleteMpduTx (peekedPacket, peekedHdr, tstamp);
+                      if (!m_txParams.MustSendRts ())
+                      {
+                        listenerIt->second->CompleteMpduTx (peekedPacket, peekedHdr, tstamp);
+                      }
+                      else
+                      {
+                        InsertInTxQueue (peekedPacket, peekedHdr, tstamp);
+                      }
                       if (retry)
                           listenerIt->second->RemoveFromBaQueue(tid, hdr.GetAddr1 (), peekedHdr.GetSequenceNumber ());
                       else
@@ -2849,6 +2880,19 @@
 {
   NS_LOG_DEBUG("Flush aggregate queue");
   m_aggregateQueue->Flush ();
+  m_txPackets.clear ();
+}
+
+void
+MacLow::InsertInTxQueue (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tStamp)
+{
+  Item item;
+  
+  item.packet = packet;
+  item.hdr = hdr;
+  item.timestamp = tStamp;
+
+  m_txPackets.push_back (item);
 }
 
 Ptr<Packet>
--- a/src/wifi/model/mac-low.h	Mon May 04 23:55:32 2015 +0200
+++ b/src/wifi/model/mac-low.h	Tue May 05 00:29:40 2015 +0200
@@ -1256,6 +1256,11 @@
    */
   bool IsAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr);
   /**
+   * Insert in a temporary queue.
+   * It is only used with a RTS/CTS exchange for an A-MPDU transmission.
+   */
+  void InsertInTxQueue (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tStamp);
+  /**
    * Perform MSDU aggregation for a given MPDU in an A-MPDU
    *
    * \param packet packet picked for aggregation
@@ -1272,6 +1277,17 @@
   Ptr<WifiPhy> m_phy; //!< Pointer to WifiPhy (actually send/receives frames)
   Ptr<WifiRemoteStationManager> m_stationManager; //!< Pointer to WifiRemoteStationManager (rate control)
   MacLowRxCallback m_rxCallback; //!< Callback to pass packet up
+    
+  /**
+   * A struct for packet, Wifi header, and timestamp.
+   */
+  typedef struct
+  {
+    Ptr<const Packet> packet;
+    WifiMacHeader hdr;
+    Time timestamp;
+  } Item;
+
   /**
    * typedef for an iterator for a list of MacLowDcfListener.
    */
@@ -1346,6 +1362,7 @@
   Ptr<WifiMacQueue> m_aggregateQueue; //!< Queue used for MPDU aggregation
   WifiMode m_currentMode;             //!< mode used for the current packet transmission
   bool m_receivedAtLeastOneMpdu;      //!< Flag whether an MPDU has already been successfully received while receiving an A-MPDU
+  std::vector<Item> m_txPackets;      //!< Contain temporary items to be sent with the next A-MPDU transmission, once RTS/CTS exchange has succeeded. It is not used in other cases.
 };
 
 } // namespace ns3