Bug 2097 [wifi] - ACKs should be sent using legacy rates and preambles in 802.11n
authorS?bastien Deronne <sebastien.deronne@gmail.com>
Wed, 06 May 2015 21:59:49 +0200
changeset 11384 935dc1cc08a4
parent 11383 d67b671e2224
child 11385 2ecfb9fd27cc
Bug 2097 [wifi] - ACKs should be sent using legacy rates and preambles in 802.11n
RELEASE_NOTES
src/wifi/examples/wifi-phy-test.cc
src/wifi/model/ap-wifi-mac.cc
src/wifi/model/constant-rate-wifi-manager.cc
src/wifi/model/constant-rate-wifi-manager.h
src/wifi/model/interference-helper.cc
src/wifi/model/interference-helper.h
src/wifi/model/mac-low.cc
src/wifi/model/mac-low.h
src/wifi/model/wifi-phy-state-helper.cc
src/wifi/model/wifi-phy-state-helper.h
src/wifi/model/wifi-phy.h
src/wifi/model/wifi-remote-station-manager.cc
src/wifi/model/yans-wifi-phy.cc
--- a/RELEASE_NOTES	Wed May 06 15:12:29 2015 +0200
+++ b/RELEASE_NOTES	Wed May 06 21:59:49 2015 +0200
@@ -50,6 +50,7 @@
 - Bug 2090 - (rip-ng) Routes may be added twice on interface activation
 - Bug 2093 - MultiModelSpectrumChannel::GetDevice only works for 0-th index
 - Bug 2095 - (wimax) Wrong values in default-traces.h for 16 QAM 3/4
+- Bug 2097 - ACKs should be sent using legacy rates and preambles in 802.11n
 - Bug 2103 - Ipv[4,6]RoutingHelper::PrintRoutingTableAll[At,Every] hangs if a node doesn't have IP
 
 Known issues
--- a/src/wifi/examples/wifi-phy-test.cc	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/examples/wifi-phy-test.cc	Wed May 06 21:59:49 2015 +0200
@@ -59,7 +59,7 @@
 
 private:
   void Send (void);
-  void Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble);
+  void Receive (Ptr<Packet> p, double snr, WifiTxVector txVector, enum WifiPreamble preamble);
   Ptr<WifiPhy> m_tx;
   struct Input m_input;
   struct Output m_output;
@@ -77,7 +77,7 @@
 }
 
 void
-PsrExperiment::Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble)
+PsrExperiment::Receive (Ptr<Packet> p, double snr, WifiTxVector txVector, enum WifiPreamble preamble)
 {
   m_output.received++;
 }
@@ -161,7 +161,7 @@
 private:
   void SendA (void) const;
   void SendB (void) const;
-  void Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble);
+  void Receive (Ptr<Packet> p, double snr, WifiTxVector txVector, enum WifiPreamble preamble);
   Ptr<WifiPhy> m_txA;
   Ptr<WifiPhy> m_txB;
   uint32_t m_flowIdA;
@@ -193,7 +193,7 @@
 }
 
 void
-CollisionExperiment::Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble)
+CollisionExperiment::Receive (Ptr<Packet> p, double snr, WifiTxVector txVector, enum WifiPreamble preamble)
 {
   FlowIdTag tag;
   if (p->FindFirstMatchingByteTag (tag))
--- a/src/wifi/model/ap-wifi-mac.cc	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/ap-wifi-mac.cc	Wed May 06 21:59:49 2015 +0200
@@ -314,6 +314,14 @@
     {
       WifiMode mode = m_phy->GetMode (i);
       rates.AddSupportedRate (mode.GetDataRate ());
+      // add rates that are part of the BSSBasicRateSet (manufacturer dependent!)
+      // here we choose to add the mandatory rates to the BSSBasicRateSet,
+      // exept for 802.11b where we assume that only the two lowest mandatory rates are part of the BSSBasicRateSet
+      if (mode.IsMandatory() &&
+         ((mode.GetModulationClass () != WIFI_MOD_CLASS_DSSS) || mode == WifiPhy::GetDsssRate1Mbps () || mode == WifiPhy::GetDsssRate2Mbps ()))
+      {
+        m_stationManager->AddBasicMode (mode);
+      }
     }
   // set the basic rates
   for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++)
--- a/src/wifi/model/constant-rate-wifi-manager.cc	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/constant-rate-wifi-manager.cc	Wed May 06 21:59:49 2015 +0200
@@ -43,7 +43,7 @@
                    StringValue ("OfdmRate6Mbps"),
                    MakeWifiModeAccessor (&ConstantRateWifiManager::m_dataMode),
                    MakeWifiModeChecker ())
-    .AddAttribute ("ControlMode", "The transmission mode to use for every control packet transmission.",
+    .AddAttribute ("ControlMode", "The transmission mode to use for every RTS packet transmission.",
                    StringValue ("OfdmRate6Mbps"),
                    MakeWifiModeAccessor (&ConstantRateWifiManager::m_ctlMode),
                    MakeWifiModeChecker ())
--- a/src/wifi/model/constant-rate-wifi-manager.h	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/constant-rate-wifi-manager.h	Wed May 06 21:59:49 2015 +0200
@@ -28,7 +28,7 @@
 
 /**
  * \ingroup wifi
- * \brief use constant rates for data and control transmissions
+ * \brief use constant rates for data and RTS transmissions
  *
  * This class uses always the same transmission rate for every
  * packet sent.
@@ -58,7 +58,7 @@
   virtual bool IsLowLatency (void) const;
 
   WifiMode m_dataMode; //!< Wifi mode for unicast DATA frames
-  WifiMode m_ctlMode; //!< Wifi mode for request control frames
+  WifiMode m_ctlMode; //!< Wifi mode for RTS frames
 };
 
 } // namespace ns3
--- a/src/wifi/model/interference-helper.cc	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/interference-helper.cc	Wed May 06 21:59:49 2015 +0200
@@ -32,16 +32,15 @@
  *       Phy event class
  ****************************************************************/
 
-InterferenceHelper::Event::Event (uint32_t size, WifiMode payloadMode,
+InterferenceHelper::Event::Event (uint32_t size, WifiTxVector txVector,
                                   enum WifiPreamble preamble,
-                                  Time duration, double rxPower, WifiTxVector txVector)
+                                  Time duration, double rxPower)
   : m_size (size),
-    m_payloadMode (payloadMode),
+    m_txVector (txVector),
     m_preamble (preamble),
     m_startTime (Simulator::Now ()),
     m_endTime (m_startTime + duration),
-    m_rxPowerW (rxPower),
-    m_txVector (txVector)
+    m_rxPowerW (rxPower)
 {
 }
 InterferenceHelper::Event::~Event ()
@@ -73,10 +72,15 @@
 {
   return m_size;
 }
+WifiTxVector
+InterferenceHelper::Event::GetTxVector (void) const
+{
+  return m_txVector;
+}
 WifiMode
 InterferenceHelper::Event::GetPayloadMode (void) const
 {
-  return m_payloadMode;
+  return m_txVector.GetMode();
 }
 enum WifiPreamble
 InterferenceHelper::Event::GetPreambleType (void) const
@@ -84,12 +88,6 @@
   return m_preamble;
 }
 
-WifiTxVector
-InterferenceHelper::Event::GetTxVector (void) const
-{
-  return m_txVector;
-}
-
 
 /****************************************************************
  *       Class which records SNIR change events for a
@@ -134,18 +132,17 @@
 }
 
 Ptr<InterferenceHelper::Event>
-InterferenceHelper::Add (uint32_t size, WifiMode payloadMode,
+InterferenceHelper::Add (uint32_t size, WifiTxVector txVector,
                          enum WifiPreamble preamble,
-                         Time duration, double rxPowerW, WifiTxVector txVector)
+                         Time duration, double rxPowerW)
 {
   Ptr<InterferenceHelper::Event> event;
 
   event = Create<InterferenceHelper::Event> (size,
-                                             payloadMode,
+                                             txVector,
                                              preamble,
                                              duration,
-                                             rxPowerW,
-                                             txVector);
+                                             rxPowerW);
   AppendEvent (event);
   return event;
 }
--- a/src/wifi/model/interference-helper.h	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/interference-helper.h	Wed May 06 21:59:49 2015 +0200
@@ -51,15 +51,15 @@
      * Create an Event with the given parameters.
      *
      * \param size packet size
-     * \param payloadMode Wi-Fi mode used for the payload
+     * \param txvector TXVECTOR of the packet
      * \param preamble preamble type
      * \param duration duration of the signal
      * \param rxPower the receive power (w)
      * \param txvector TXVECTOR of the packet
      */
-    Event (uint32_t size, WifiMode payloadMode,
+    Event (uint32_t size, WifiTxVector txvector,
            enum WifiPreamble preamble,
-           Time duration, double rxPower, WifiTxVector txvector);
+           Time duration, double rxPower);
     ~Event ();
 
     /**
@@ -93,6 +93,12 @@
      */
     uint32_t GetSize (void) const;
     /**
+     * Return the TXVECTOR of the packet.
+     *
+     * \return the TXVECTOR of the packet
+     */
+    WifiTxVector GetTxVector (void) const;
+    /**
      * Return the Wi-Fi mode used for the payload.
      *
      * \return the Wi-Fi mode used for the payload
@@ -104,20 +110,14 @@
      * \return the preamble type of the packet
      */
     enum WifiPreamble GetPreambleType (void) const;
-    /**
-     * Return the TXVECTOR of the packet.
-     *
-     * \return the TXVECTOR of the packet
-     */
-    WifiTxVector GetTxVector (void) const;
+
 private:
     uint32_t m_size;
-    WifiMode m_payloadMode;
+    WifiTxVector m_txVector;
     enum WifiPreamble m_preamble;
     Time m_startTime;
     Time m_endTime;
     double m_rxPowerW;
-    WifiTxVector m_txVector;
   };
   /**
    * A struct for both SNR and PER
@@ -170,16 +170,15 @@
    * Add the packet-related signal to interference helper.
    *
    * \param size packet size
-   * \param payloadMode Wi-Fi mode for the payload
+   * \param txvector TXVECTOR of the packet
    * \param preamble Wi-Fi preamble for the packet
    * \param duration the duration of the signal
    * \param rxPower receive power (w)
-   * \param txvector TXVECTOR of the packet
    * \return InterferenceHelper::Event
    */
-  Ptr<InterferenceHelper::Event> Add (uint32_t size, WifiMode payloadMode,
+  Ptr<InterferenceHelper::Event> Add (uint32_t size, WifiTxVector txvector,
                                       enum WifiPreamble preamble,
-                                      Time duration, double rxPower, WifiTxVector txvector);
+                                      Time duration, double rxPower);
 
   /**
    * Calculate the SNIR at the start of the plcp payload and accumulate
--- a/src/wifi/model/mac-low.cc	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/mac-low.cc	Wed May 06 21:59:49 2015 +0200
@@ -519,7 +519,7 @@
 void
 MacLow::ResetPhy (void)
 {
-  m_phy->SetReceiveOkCallback (MakeNullCallback<void,Ptr<Packet>, double, WifiMode, enum WifiPreamble>  ());
+  m_phy->SetReceiveOkCallback (MakeNullCallback<void,Ptr<Packet>, double, WifiTxVector, enum WifiPreamble>  ());
   m_phy->SetReceiveErrorCallback (MakeNullCallback<void,Ptr<const Packet>, double> ());
   RemovePhyMacLowListener (m_phy);
   m_phy = 0;
@@ -775,7 +775,7 @@
                                                 hdr.GetQosTid(),
                                                 hdr.GetAddr2 (),
                                                 hdr.GetDuration (),
-                                                m_currentMode);
+                                                m_currentTxVector);
         }
       else if (hdr.IsBlockAckReq())
         {
@@ -824,9 +824,9 @@
 }
 
 void
-MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamble preamble, bool ampduSubframe)
+MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, WifiPreamble preamble, bool ampduSubframe)
 {
-  NS_LOG_FUNCTION (this << packet << rxSnr << txMode << preamble);
+  NS_LOG_FUNCTION (this << packet << rxSnr << txVector.GetMode () << preamble);
   /* A packet is received from the PHY.
    * When we have handled this packet,
    * we handle any packet present in the
@@ -837,7 +837,7 @@
 
   bool isPrevNavZero = IsNavZero ();
   NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
-  NotifyNav (packet,hdr, txMode, preamble);
+  NotifyNav (packet, hdr, preamble);
   if (hdr.IsRts ())
     {
       /* see section 9.2.5.7 802.11-1999
@@ -858,12 +858,12 @@
               NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
               NS_ASSERT (m_sendCtsEvent.IsExpired ());
               m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
-                                            rxSnr, txMode);
+                                            rxSnr, txVector.GetMode ());
               m_sendCtsEvent = Simulator::Schedule (GetSifs (),
                                                     &MacLow::SendCtsAfterRts, this,
                                                     hdr.GetAddr2 (),
                                                     hdr.GetDuration (),
-                                                    txMode,
+                                                    txVector,
                                                     rxSnr);
             }
           else
@@ -885,19 +885,18 @@
       SnrTag tag;
       packet->RemovePacketTag (tag);
       m_stationManager->ReportRxOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
-                                    rxSnr, txMode);
+                                    rxSnr, txVector.GetMode ());
       m_stationManager->ReportRtsOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
-                                     rxSnr, txMode, tag.Get ());
+                                     rxSnr, txVector.GetMode (), tag.Get ());
 
       m_ctsTimeoutEvent.Cancel ();
       NotifyCtsTimeoutResetNow ();
-      m_listener->GotCts (rxSnr, txMode);
+      m_listener->GotCts (rxSnr, txVector.GetMode ());
       NS_ASSERT (m_sendDataEvent.IsExpired ());
       m_sendDataEvent = Simulator::Schedule (GetSifs (),
                                              &MacLow::SendDataAfterCts, this,
                                              hdr.GetAddr1 (),
-                                             hdr.GetDuration (),
-                                             txMode);
+                                             hdr.GetDuration ());
     }
   else if (hdr.IsAck ()
            && hdr.GetAddr1 () == m_self
@@ -910,9 +909,9 @@
       SnrTag tag;
       packet->RemovePacketTag (tag);
       m_stationManager->ReportRxOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
-                                    rxSnr, txMode);
+                                    rxSnr, txVector.GetMode ());
       m_stationManager->ReportDataOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
-                                      rxSnr, txMode, tag.Get ());
+                                      rxSnr, txVector.GetMode (), tag.Get ());
 
       FlushAggregateQueue();
       bool gotAck = false;
@@ -932,7 +931,7 @@
         }
       if (gotAck)
         {
-          m_listener->GotAck (rxSnr, txMode);
+          m_listener->GotAck (rxSnr, txVector.GetMode ());
         }
       if (m_txParams.HasNextPacket ())
         {
@@ -949,7 +948,7 @@
       packet->RemoveHeader (blockAck);
       m_blockAckTimeoutEvent.Cancel ();
       NotifyAckTimeoutResetNow ();
-      m_listener->GotBlockAck (&blockAck, hdr.GetAddr2 (),txMode);
+      m_listener->GotBlockAck (&blockAck, hdr.GetAddr2 (), txVector.GetMode ());
       m_sentMpdus = 0;
       m_ampdu = false;
       FlushAggregateQueue();
@@ -980,7 +979,7 @@
                                                         blockAckReq,
                                                         hdr.GetAddr2 (),
                                                         hdr.GetDuration (),
-                                                        txMode);
+                                                        txVector.GetMode ());
                 }
               else
                 {
@@ -1006,7 +1005,7 @@
   else if (hdr.GetAddr1 () == m_self)
     {
       m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
-                                    rxSnr, txMode);
+                                    rxSnr, txVector.GetMode ());
       if (hdr.IsQosData () && ReceiveMpdu (packet, hdr))
         {
           /* From section 9.10.4 in IEEE 802.11:
@@ -1027,7 +1026,7 @@
                                                     &MacLow::SendAckAfterData, this,
                                                     hdr.GetAddr2 (),
                                                     hdr.GetDuration (),
-                                                    txMode,
+                                                    txVector.GetMode (),
                                                     rxSnr);
               m_receivedAtLeastOneMpdu = false;
             }
@@ -1078,7 +1077,7 @@
                                                     &MacLow::SendAckAfterData, this,
                                                     hdr.GetAddr2 (),
                                                     hdr.GetDuration (),
-                                                    txMode,
+                                                    txVector.GetMode (),
                                                     rxSnr);
             }
         }
@@ -1183,32 +1182,24 @@
 Time
 MacLow::GetAckDuration (Mac48Address to, WifiTxVector dataTxVector) const
 {
-  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode());
+  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode ());
   return GetAckDuration (ackTxVector);
 }
 Time
 MacLow::GetAckDuration (WifiTxVector ackTxVector) const
 {
-  WifiPreamble preamble;
-  if (ackTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
-  else
-    preamble=WIFI_PREAMBLE_LONG;
-  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble, m_phy->GetFrequency(), 0, 0);
+  NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); // ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
+  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, WIFI_PREAMBLE_LONG, m_phy->GetFrequency(), 0, 0);
 }
 Time
 MacLow::GetBlockAckDuration (Mac48Address to, WifiTxVector blockAckReqTxVector, enum BlockAckType type) const
 {
   /*
-   * For immediate BlockAck we should transmit the frame with the same WifiMode
+   * For immediate Basic BlockAck we should transmit the frame with the same WifiMode
    * as the BlockAckReq.
-   *
-   * from section 9.6 in IEEE 802.11e:
-   * The BlockAck control frame shall be sent at the same rate and modulation class as
-   * the BlockAckReq frame if it is sent in response to a BlockAckReq frame.
    */
   WifiPreamble preamble;
-  if (blockAckReqTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
+  if (blockAckReqTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT && type == BASIC_BLOCK_ACK)
     preamble= WIFI_PREAMBLE_HT_MF;
   else
     preamble=WIFI_PREAMBLE_LONG;
@@ -1217,19 +1208,15 @@
 Time
 MacLow::GetCtsDuration (Mac48Address to, WifiTxVector rtsTxVector) const
 {
-  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode());
+  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode ());
   return GetCtsDuration (ctsTxVector);
 }
 
 Time
 MacLow::GetCtsDuration (WifiTxVector ctsTxVector) const
 {
-  WifiPreamble preamble;
-  if (ctsTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
-  else
-    preamble=WIFI_PREAMBLE_LONG;
-  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency(), 0, 0);
+  NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); // CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
+  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, WIFI_PREAMBLE_LONG, m_phy->GetFrequency(), 0, 0);
 }
 uint32_t
 MacLow::GetCtsSize (void) const
@@ -1314,12 +1301,9 @@
         {
           preamble = WIFI_PREAMBLE_HT_GF;
         }
-      else if (rtsTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
-        {
-          preamble = WIFI_PREAMBLE_HT_MF;
-        }
       else
         {
+          //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
           preamble = WIFI_PREAMBLE_LONG;
         }
       txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency(), 0, 0);
@@ -1327,13 +1311,10 @@
       txTime += Time (GetSifs () * 2);
     }
   WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
-  //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
   if ( m_phy->GetGreenfield()&& m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
-    preamble= WIFI_PREAMBLE_HT_GF;
-  else if (dataTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
-  else
-    preamble=WIFI_PREAMBLE_LONG;
+    preamble = WIFI_PREAMBLE_HT_GF;
+  else //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
+    preamble = WIFI_PREAMBLE_LONG;
   uint32_t dataSize = GetSize (packet, hdr);
   txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
   if (params.MustWaitAck ())
@@ -1354,7 +1335,7 @@
     {
       WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
       WifiPreamble preamble;
-        //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
+      //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
       if ( m_phy->GetGreenfield()&& m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
          preamble= WIFI_PREAMBLE_HT_GF;
       else if (dataTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
@@ -1368,7 +1349,7 @@
 }
 
 void
-MacLow::NotifyNav (Ptr<const Packet> packet,const WifiMacHeader &hdr, WifiMode txMode, WifiPreamble preamble)
+MacLow::NotifyNav (Ptr<const Packet> packet,const WifiMacHeader &hdr, WifiPreamble preamble)
 {
   NS_ASSERT (m_lastNavStart <= Simulator::Now ());
   Time duration = hdr.GetDuration ();
@@ -1486,7 +1467,7 @@
   NS_LOG_DEBUG ("send " << hdr->GetTypeString () <<
                 ", to=" << hdr->GetAddr1 () <<
                 ", size=" << packet->GetSize () <<
-                ", mode=" << txVector.GetMode() <<
+                ", mode=" << txVector.GetMode  () <<
                 ", duration=" << hdr->GetDuration () <<
                 ", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec);
   if (!m_ampdu || hdr->IsRts ())
@@ -1649,12 +1630,10 @@
 
   WifiPreamble preamble;
   //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
-  if ( m_phy->GetGreenfield()&& m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
+  if (m_phy->GetGreenfield () && m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
     preamble= WIFI_PREAMBLE_HT_GF;
-  else if (rtsTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
-  else
-    preamble=WIFI_PREAMBLE_LONG;
+  else //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
+    preamble = WIFI_PREAMBLE_LONG;
 
   if (m_txParams.HasDurationId ())
     {
@@ -1671,12 +1650,12 @@
       duration += GetSifs ();
       if (m_txParams.MustWaitBasicBlockAck ())
         {
-          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2(), dataTxVector.GetMode());
+          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2(), dataTxVector.GetMode  ());
           duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
         }
       else if (m_txParams.MustWaitCompressedBlockAck ())
         {
-          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2(), dataTxVector.GetMode());
+          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2(), dataTxVector.GetMode  ());
           duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
         }
       else if (m_txParams.MustWaitAck ())
@@ -1718,11 +1697,11 @@
  
   //Since it is data then it can have format = GF
   if (m_phy->GetGreenfield() && m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
-    preamble= WIFI_PREAMBLE_HT_GF;
-  else if (dataTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
+    preamble = WIFI_PREAMBLE_HT_GF;
+  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
+    preamble = WIFI_PREAMBLE_HT_MF;
   else
-    preamble=WIFI_PREAMBLE_LONG;
+    preamble = WIFI_PREAMBLE_LONG;
  
   Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
   if (m_txParams.MustWaitNormalAck ())
@@ -1793,11 +1772,11 @@
           
   if (m_phy->GetGreenfield() && m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
      //In the future has to make sure that receiver has greenfield enabled
-     preamble= WIFI_PREAMBLE_HT_GF;
-  else if (dataTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
+     preamble = WIFI_PREAMBLE_HT_GF;
+  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
+    preamble = WIFI_PREAMBLE_HT_MF;
   else
-     preamble=WIFI_PREAMBLE_LONG;
+     preamble = WIFI_PREAMBLE_LONG;
   
   StartDataTxTimers (dataTxVector);
 
@@ -1811,13 +1790,13 @@
       if (m_txParams.MustWaitBasicBlockAck ())
         {
           duration += GetSifs ();
-          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
           duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
         }
       else if (m_txParams.MustWaitCompressedBlockAck ())
         {
           duration += GetSifs ();
-          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
           duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
         }
       else if (m_txParams.MustWaitAck ())
@@ -1846,7 +1825,7 @@
       m_currentPacket->AddTrailer (fcs);
     }
 
-  ForwardDown (m_currentPacket, &m_currentHdr, dataTxVector,preamble);
+  ForwardDown (m_currentPacket, &m_currentHdr, dataTxVector, preamble);
   m_currentPacket = 0;
 }
 
@@ -1876,10 +1855,10 @@
   WifiTxVector ctsTxVector = GetCtsToSelfTxVector (m_currentPacket, &m_currentHdr);
 
   WifiPreamble preamble;
-  if (ctsTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
+  if (ctsTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
+    preamble = WIFI_PREAMBLE_HT_MF;
   else
-    preamble=WIFI_PREAMBLE_LONG;
+    preamble = WIFI_PREAMBLE_LONG;
   
   Time duration = Seconds (0);
 
@@ -1897,13 +1876,13 @@
         {
           
           duration += GetSifs ();
-          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
           duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
         }
       else if (m_txParams.MustWaitCompressedBlockAck ())
         {
           duration += GetSifs ();
-          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+          WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
           duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
         }
       else if (m_txParams.MustWaitAck ())
@@ -1919,7 +1898,7 @@
           if (m_txParams.MustWaitCompressedBlockAck ())
             {
               duration += GetSifs ();
-              WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+              WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
               duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
             }
           else if (m_txParams.MustWaitAck ())
@@ -1946,17 +1925,16 @@
   m_sendDataEvent = Simulator::Schedule (txDuration,
                                          &MacLow::SendDataAfterCts, this,
                                          cts.GetAddr1 (),
-                                         duration,
-                                         ctsTxVector.GetMode());
+                                         duration);
 }
 void
-MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiMode rtsTxMode, double rtsSnr)
+MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
 {
-  NS_LOG_FUNCTION (this << source << duration << rtsTxMode << rtsSnr);
+  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
   /* send a CTS when you receive a RTS
    * right after SIFS.
    */
- WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxMode);
+  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
   WifiMacHeader cts;
   cts.SetType (WIFI_MAC_CTL_CTS);
   cts.SetDsNotFrom ();
@@ -1964,7 +1942,7 @@
   cts.SetNoMoreFragments ();
   cts.SetNoRetry ();
   cts.SetAddr1 (source);
-  duration -= GetCtsDuration (source, ctsTxVector);
+  duration -= GetCtsDuration (source, rtsTxVector);
   duration -= GetSifs ();
   NS_ASSERT (duration >= MicroSeconds (0));
   cts.SetDuration (duration);
@@ -1978,16 +1956,12 @@
   tag.Set (rtsSnr);
   packet->AddPacketTag (tag);
 
-  WifiPreamble preamble;
-  if (ctsTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
-  else
-    preamble=WIFI_PREAMBLE_LONG;
-  ForwardDown (packet, &cts, ctsTxVector,preamble);
+  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
+  ForwardDown (packet, &cts, ctsTxVector, WIFI_PREAMBLE_LONG);
 }
 
 void
-MacLow::SendDataAfterCts (Mac48Address source, Time duration, WifiMode txMode)
+MacLow::SendDataAfterCts (Mac48Address source, Time duration)
 {
   NS_LOG_FUNCTION (this);
   /* send the third step in a
@@ -2010,26 +1984,26 @@
   }
   
   WifiPreamble preamble;       
-  if (m_phy->GetGreenfield() && m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
+  if (m_phy->GetGreenfield () && m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
      //In the future has to make sure that receiver has greenfield enabled
-     preamble= WIFI_PREAMBLE_HT_GF;
-  else if (dataTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
+     preamble = WIFI_PREAMBLE_HT_GF;
+  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
+    preamble = WIFI_PREAMBLE_HT_MF;
   else
-     preamble=WIFI_PREAMBLE_LONG;
+     preamble = WIFI_PREAMBLE_LONG;
   
   StartDataTxTimers (dataTxVector);
   Time newDuration = Seconds (0);
   if (m_txParams.MustWaitBasicBlockAck ())
     {
       newDuration += GetSifs ();
-      WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+      WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
       newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
     }
   else if (m_txParams.MustWaitCompressedBlockAck ())
     {
       newDuration += GetSifs ();
-      WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+      WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
       newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
     }
   else if (m_txParams.MustWaitAck ())
@@ -2044,7 +2018,7 @@
       if (m_txParams.MustWaitCompressedBlockAck ())
         {
            newDuration += GetSifs ();
-           WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode());
+           WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
            newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
         }
       else if (m_txParams.MustWaitAck ())
@@ -2126,13 +2100,8 @@
   tag.Set (dataSnr);
   packet->AddPacketTag (tag);
 
-   //since ACK is a control response it can't have format GF
-  WifiPreamble preamble;
-  if (ackTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
-  else
-    preamble=WIFI_PREAMBLE_LONG;
-  ForwardDown (packet, &ack, ackTxVector, preamble);
+  //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
+  ForwardDown (packet, &ack, ackTxVector, WIFI_PREAMBLE_LONG);
 }
 
 bool
@@ -2422,15 +2391,15 @@
   WifiMacTrailer fcs;
   packet->AddTrailer (fcs);
   WifiPreamble preamble;
-  if (blockAckReqTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
-    preamble= WIFI_PREAMBLE_HT_MF;
+  if (blockAckReqTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
+    preamble = WIFI_PREAMBLE_HT_MF;
   else
-    preamble=WIFI_PREAMBLE_LONG;
+    preamble = WIFI_PREAMBLE_LONG;
   ForwardDown (packet, &hdr, blockAckReqTxVector, preamble);
   m_currentPacket = 0;
 }
 void 
-MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiMode blockAckReqTxMode)
+MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector)
 {
   NS_LOG_FUNCTION (this);
   CtrlBAckResponseHeader blockAck;
@@ -2448,7 +2417,7 @@
   NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
   (*i).second.FillBlockAckBitmap (&blockAck);  
 
-  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode);
+  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxVector.GetMode  ());
 }
 
 void
@@ -2547,9 +2516,9 @@
 }
 
 void
-MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiMode txMode, WifiPreamble preamble)
+MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble)
 {
-  m_currentMode = txMode;
+  m_currentTxVector = txVector;
   AmpduTag ampdu;
   bool normalAck = false;
   bool ampduSubframe = false;
@@ -2562,16 +2531,16 @@
       WifiMacHeader firsthdr;
       (*n).first->PeekHeader(firsthdr);
       NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ());
-      NotifyNav ((*n).first,firsthdr, txMode, preamble);
+      NotifyNav ((*n).first, firsthdr, preamble);
       if (firsthdr.GetAddr1 () == m_self)
         {
           m_receivedAtLeastOneMpdu = true;
           if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
-              ReceiveOk ((*n).first, rxSnr, txMode, preamble, ampduSubframe);
+              ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe);
           else if (firsthdr.IsData () || firsthdr.IsQosData ())
             {
               NS_LOG_DEBUG ("Deaagregate packet with sequence=" << firsthdr.GetSequenceNumber ());
-              ReceiveOk ((*n).first, rxSnr, txMode, preamble, ampduSubframe);
+              ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe);
               if (firsthdr.IsQosAck ())
                 {
                   NS_LOG_DEBUG ("Normal Ack");
@@ -2602,7 +2571,7 @@
                                                     firsthdr.GetQosTid(),
                                                     firsthdr.GetAddr2 (),
                                                     firsthdr.GetDuration (),
-                                                    txMode);
+                                                    txVector);
             } 
           else
             { 
@@ -2613,7 +2582,7 @@
     }
   else
     {     
-          ReceiveOk (aggregatedPacket,rxSnr, txMode, preamble, ampduSubframe);
+          ReceiveOk (aggregatedPacket,rxSnr, txVector, preamble, ampduSubframe);
     }
 }
 
@@ -2624,14 +2593,14 @@
     WifiTxVector dataTxVector = GetDataTxVector (m_currentPacket, &m_currentHdr);
     if (m_phy->GetGreenfield () && m_stationManager->GetGreenfieldSupported (m_currentHdr.GetAddr1 ()))
         preamble = WIFI_PREAMBLE_HT_GF;
-    else
-        preamble = WIFI_PREAMBLE_HT_MF;
+    else //Block ACK following implicit BAR always use non-HT PPDU
+        preamble = WIFI_PREAMBLE_LONG;
     
     if (peekedPacket == 0)
         return true;
     
     //An HT STA shall not transmit a PPDU that has a duration that is greater than aPPDUMaxTime (10 milliseconds)
-    if(m_phy->CalculateTxDuration (aggregatedPacket->GetSize () + peekedPacket->GetSize () + peekedHdr.GetSize () +WIFI_MAC_FCS_LENGTH,dataTxVector, preamble, m_phy->GetFrequency(), 0, 0) > MilliSeconds(10))
+    if(m_phy->CalculateTxDuration (aggregatedPacket->GetSize () + peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, dataTxVector, preamble, m_phy->GetFrequency(), 0, 0) > MilliSeconds(10))
         return true;
     
     if (!m_mpduAggregator->CanBeAggregated (peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, aggregatedPacket, size))
--- a/src/wifi/model/mac-low.h	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/mac-low.h	Wed May 06 21:59:49 2015 +0200
@@ -711,14 +711,14 @@
   /**
    * \param packet packet received
    * \param rxSnr snr of packet received
-   * \param txMode transmission mode of packet received
+   * \param txVector TXVECTOR of packet received
    * \param preamble type of preamble used for the packet received
    * \param ampduSubframe true if this MPDU is part of an A-MPDU
    *
    * This method is typically invoked by the lower PHY layer to notify
    * the MAC layer that a packet was successfully received.
    */
-  void ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamble preamble, bool ampduSubframe);
+  void ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, WifiPreamble preamble, bool ampduSubframe);
   /**
    * \param packet packet received.
    * \param rxSnr snr of packet received.
@@ -788,13 +788,13 @@
   /**
    * \param aggregatedPacket which is the current A-MPDU
    * \param rxSnr snr of packet received
-   * \param txMode transmission mode of packet received
-   * \param preamble type of preamble used for the packet received        
+   * \param txVector TXVECTOR of packet received
+   * \param preamble type of preamble used for the packet received
    *
    * This function de-aggregates an A-MPDU and decide if each MPDU is received correctly or not
    * 
    */
-  void DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiMode txMode, WifiPreamble preamble);
+  void DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble);
   /**
    * \param peekedPacket the packet to be aggregated
    * \param peekedHdr the WifiMacHeader for the packet.
@@ -1011,7 +1011,7 @@
   Time CalculateOverallTxTime (Ptr<const Packet> packet,
                                const WifiMacHeader* hdr,
                                const MacLowTransmissionParameters &params) const;
-  void NotifyNav (Ptr<const Packet> packet,const WifiMacHeader &hdr, WifiMode txMode, WifiPreamble preamble);
+  void NotifyNav (Ptr<const Packet> packet,const WifiMacHeader &hdr, WifiPreamble preamble);
   /**
    * Reset NAV with the given duration.
    *
@@ -1099,10 +1099,10 @@
    *
    * \param source
    * \param duration
-   * \param txMode
+   * \param rtsTxVector
    * \param rtsSnr
    */
-  void SendCtsAfterRts (Mac48Address source, Time duration, WifiMode txMode, double rtsSnr);
+  void SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr);
   /**
    * Send ACK after receiving DATA.
    *
@@ -1117,9 +1117,8 @@
    *
    * \param source
    * \param duration
-   * \param txMode
    */
-  void SendDataAfterCts (Mac48Address source, Time duration, WifiMode txMode);
+  void SendDataAfterCts (Mac48Address source, Time duration);
   /**
    * Event handler that is usually scheduled to fired at the appropriate time
    * after completing transmissions.
@@ -1213,7 +1212,7 @@
    * block ack agreement and creates block ack bitmap on a received packets basis.
    */
   void SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator,
-                                          Time duration, WifiMode blockAckReqTxMode);
+                                          Time duration, WifiTxVector blockAckReqTxVector);
   /**
    * This method creates block ack frame with header equals to <i>blockAck</i> and start its transmission.
    *
@@ -1360,7 +1359,7 @@
   bool m_ctsToSelfSupported;          //!< Flag whether CTS-to-self is supported
   uint8_t m_sentMpdus;                //!< Number of transmitted MPDUs in an A-MPDU that have not been acknowledged yet
   Ptr<WifiMacQueue> m_aggregateQueue; //!< Queue used for MPDU aggregation
-  WifiMode m_currentMode;             //!< mode used for the current packet transmission
+  WifiTxVector m_currentTxVector;     //!< TXVECTOR 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.
 };
--- a/src/wifi/model/wifi-phy-state-helper.cc	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/wifi-phy-state-helper.cc	Wed May 06 21:59:49 2015 +0200
@@ -415,14 +415,14 @@
 }
 
 void
-WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble)
+WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<Packet> packet, double snr, WifiTxVector txVector, enum WifiPreamble preamble)
 {
-  m_rxOkTrace (packet, snr, mode, preamble);
+  m_rxOkTrace (packet, snr, txVector.GetMode(), preamble);
   NotifyRxEndOk ();
   DoSwitchFromRx ();
   if (!m_rxOkCallback.IsNull ())
     {
-      m_rxOkCallback (packet, snr, mode, preamble);
+      m_rxOkCallback (packet, snr, txVector, preamble);
     }
 
 }
--- a/src/wifi/model/wifi-phy-state-helper.h	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/wifi-phy-state-helper.h	Wed May 06 21:59:49 2015 +0200
@@ -157,10 +157,10 @@
    *
    * \param packet the successfully received packet
    * \param snr the SNR of the received packet
-   * \param mode the transmission mode of the packet
+   * \param txVector TXVECTOR of the packet
    * \param preamble the preamble of the received packet
    */
-  void SwitchFromRxEndOk (Ptr<Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble);
+  void SwitchFromRxEndOk (Ptr<Packet> packet, double snr, WifiTxVector txVector, enum WifiPreamble preamble);
   /**
    * Switch from RX after the reception failed.
    *
--- a/src/wifi/model/wifi-phy.h	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/wifi-phy.h	Wed May 06 21:59:49 2015 +0200
@@ -160,10 +160,10 @@
   /**
    * arg1: packet received successfully
    * arg2: snr of packet
-   * arg3: mode of packet
+   * arg3: TXVECTOR of packet
    * arg4: type of preamble used for packet.
    */
-  typedef Callback<void,Ptr<Packet>, double, WifiMode, enum WifiPreamble> RxOkCallback;
+  typedef Callback<void,Ptr<Packet>, double, WifiTxVector, enum WifiPreamble> RxOkCallback;
   /**
    * arg1: packet received unsuccessfully
    * arg2: snr of packet
--- a/src/wifi/model/wifi-remote-station-manager.cc	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/wifi-remote-station-manager.cc	Wed May 06 21:59:49 2015 +0200
@@ -935,8 +935,9 @@
        i != m_bssBasicRateSet.end (); i++)
     {
       if ((!found || i->GetPhyRate () > mode.GetPhyRate ())
-          && i->GetPhyRate () <= reqMode.GetPhyRate ()
-          && i->GetModulationClass () == reqMode.GetModulationClass ())
+          && (i->GetPhyRate () <= reqMode.GetPhyRate ())
+          && ((i->GetModulationClass () == reqMode.GetModulationClass ())
+              || (reqMode.GetModulationClass () == WIFI_MOD_CLASS_HT)))
         {
           mode = *i;
           // We've found a potentially-suitable transmit rate, but we
@@ -946,13 +947,13 @@
         }
     }
   if(HasHtSupported())
-      {
-        if (!found)
-          {
-            uint8_t mcs = GetDefaultMcs (); 
-            mode=  m_wifiPhy->McsToWifiMode (mcs); 
-          }
-        for (WifiMcsListIterator i = m_bssBasicMcsSet.begin ();
+    {
+      if (!found)
+        {
+          uint8_t mcs = GetDefaultMcs ();
+          mode = m_wifiPhy->McsToWifiMode (mcs);
+            
+          for (WifiMcsListIterator i = m_bssBasicMcsSet.begin ();
              i != m_bssBasicMcsSet.end (); i++)
           {
             WifiMode thismode=  m_wifiPhy->McsToWifiMode (*i); 
@@ -967,11 +968,13 @@
                 found = true;
               }
           }
+        }
       }
   // If we found a suitable rate in the BSSBasicRateSet, then we are
   // done and can return that mode.
   if (found)
     {
+      NS_LOG_DEBUG ("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
       return mode;
     }
 
@@ -1007,8 +1010,9 @@
        */
       if (thismode.IsMandatory ()
           && (!found || thismode.GetPhyRate () > mode.GetPhyRate ())
-          && thismode.GetPhyRate () <= reqMode.GetPhyRate ()
-          && thismode.GetModulationClass () == reqMode.GetModulationClass ())
+          && (thismode.GetPhyRate () <= reqMode.GetPhyRate ())
+          && ((thismode.GetModulationClass () == reqMode.GetModulationClass ()) ||
+             (reqMode.GetModulationClass () == WIFI_MOD_CLASS_HT)))
         {
           mode = thismode;
           // As above; we've found a potentially-suitable transmit
--- a/src/wifi/model/yans-wifi-phy.cc	Wed May 06 15:12:29 2015 +0200
+++ b/src/wifi/model/yans-wifi-phy.cc	Wed May 06 21:59:49 2015 +0200
@@ -529,7 +529,6 @@
   // Note: plcp preamble reception is not yet modeled.
   NS_LOG_FUNCTION (this << packet << rxPowerDbm << txVector.GetMode()<< preamble << (uint32_t)packetType);
   AmpduTag ampduTag;
-  WifiMode txMode = txVector.GetMode();
   
   rxPowerDbm += m_rxGainDb;
   double rxPowerW = DbmToW (rxPowerDbm);
@@ -538,11 +537,10 @@
 
   Ptr<InterferenceHelper::Event> event;
   event = m_interference.Add (packet->GetSize (),
-                              txMode,
+                              txVector,
                               preamble,
                               rxDuration,
-                              rxPowerW,
-                              txVector);
+                              rxPowerW);
     
   switch (m_state->GetState ())
     {
@@ -1036,7 +1034,7 @@
       double signalDbm = RatioToDb (event->GetRxPowerW ()) + 30;
       double noiseDbm = RatioToDb (event->GetRxPowerW () / snrPer.snr) - GetRxNoiseFigure () + 30;
       NotifyMonitorSniffRx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, isShortPreamble, signalDbm, noiseDbm);
-      m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetPayloadMode (), event->GetPreambleType ());
+      m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetTxVector (), event->GetPreambleType ());
     }
     else
     {