add support for HT MCS and A-MPDU in radiotap headers
authorSébastien Deronne <sebastien.deronne@gmail.com>
Wed, 08 Jul 2015 23:44:17 +0200
changeset 11479 a3dcf66928f3
parent 11478 f743110af92e
child 11480 e16a7d8c558f
add support for HT MCS and A-MPDU in radiotap headers
src/network/utils/radiotap-header.cc
src/network/utils/radiotap-header.h
src/wave/helper/wave-helper.cc
src/wifi/examples/test-interference-helper.cc
src/wifi/examples/wifi-phy-test.cc
src/wifi/helper/yans-wifi-helper.cc
src/wifi/model/aarf-wifi-manager.cc
src/wifi/model/aarfcd-wifi-manager.cc
src/wifi/model/amrr-wifi-manager.cc
src/wifi/model/aparf-wifi-manager.cc
src/wifi/model/arf-wifi-manager.cc
src/wifi/model/cara-wifi-manager.cc
src/wifi/model/constant-rate-wifi-manager.cc
src/wifi/model/ideal-wifi-manager.cc
src/wifi/model/mac-low.cc
src/wifi/model/mac-low.h
src/wifi/model/minstrel-wifi-manager.cc
src/wifi/model/onoe-wifi-manager.cc
src/wifi/model/parf-wifi-manager.cc
src/wifi/model/rraa-wifi-manager.cc
src/wifi/model/wifi-phy.cc
src/wifi/model/wifi-phy.h
src/wifi/model/wifi-remote-station-manager.cc
src/wifi/model/wifi-remote-station-manager.h
src/wifi/model/wifi-tx-vector.cc
src/wifi/model/wifi-tx-vector.h
src/wifi/model/yans-wifi-channel.cc
src/wifi/model/yans-wifi-channel.h
src/wifi/model/yans-wifi-phy.cc
src/wifi/model/yans-wifi-phy.h
--- a/src/network/utils/radiotap-header.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/network/utils/radiotap-header.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -3,7 +3,7 @@
  * Copyright (c) 2009 CTTC
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as 
+ * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation;
  *
  * This program is distributed in the hope that it will be useful,
@@ -15,7 +15,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Include., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Author: Nicola Baldo <nbaldo@cttc.es>
+ * Authors: Nicola Baldo <nbaldo@cttc.es>
+ *          Sébastien Deronne <sebastien.deronne@gmail.com>
  */
 
 #include <iomanip>
@@ -28,8 +29,8 @@
 NS_LOG_COMPONENT_DEFINE ("RadiotapHeader");
 
 NS_OBJECT_ENSURE_REGISTERED (RadiotapHeader);
- 
-RadiotapHeader::RadiotapHeader()
+
+RadiotapHeader::RadiotapHeader ()
   : m_length (8),
     m_present (0),
     m_tsft (0),
@@ -38,23 +39,26 @@
     m_channelFreq (0),
     m_channelFlags (CHANNEL_FLAG_NONE),
     m_antennaSignal (0),
-    m_antennaNoise (0)
+    m_antennaNoise (0),
+    m_ampduStatusRef (0),
+    m_ampduStatusFlags (0),
+    m_ampduStatusCRC (0)
 {
   NS_LOG_FUNCTION (this);
 }
- 
+
 TypeId RadiotapHeader::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::RadiotapHeader")
     .SetParent<Header> ()
-    .SetGroupName("Network")
+    .SetGroupName ("Network")
 
     .AddConstructor<RadiotapHeader> ()
   ;
   return tid;
 }
 
-TypeId 
+TypeId
 RadiotapHeader::GetInstanceTypeId (void) const
 {
   return GetTypeId ();
@@ -78,7 +82,7 @@
   start.WriteU32 (m_present); // bits describing which fields follow header
 
   //
-  // Time Synchronization Function Timer (when the first bit of the MPDU 
+  // Time Synchronization Function Timer (when the first bit of the MPDU
   // arrived at the MAC)
   //
   if (m_present & RADIOTAP_TSFT) // bit 0
@@ -107,11 +111,21 @@
   //
   if (m_present & RADIOTAP_CHANNEL) // bit 3
     {
+      start.WriteU8 (0, m_channelPad);
       start.WriteU16 (m_channelFreq);
       start.WriteU16 (m_channelFlags);
     }
 
   //
+  // The hop set and pattern for frequency-hopping radios.  We don't need it but
+  // still need to account for it.
+  //
+  if (m_present & RADIOTAP_FHSS) // bit 4
+    {
+      start.WriteU8 (0); //not yet implemented
+    }
+
+  //
   // RF signal power at the antenna, decibel difference from an arbitrary, fixed
   // reference.
   //
@@ -121,13 +135,121 @@
     }
 
   //
-  // RF noise power at the antenna, decibel difference from an arbitrary, fixed 
+  // RF noise power at the antenna, decibel difference from an arbitrary, fixed
   // reference.
   //
   if (m_present & RADIOTAP_DBM_ANTNOISE) // bit 6
     {
       start.WriteU8 (m_antennaNoise);
     }
+
+  //
+  // Quality of Barker code lock.
+  //
+  if (m_present & RADIOTAP_LOCK_QUALITY) // bit 7
+    {
+      start.WriteU16 (0); //not yet implemented
+    }
+
+  //
+  // Transmit power expressed as unitless distance from max power
+  // set at factory calibration (0 is max power).
+  //
+  if (m_present & RADIOTAP_TX_ATTENUATION) // bit 8
+    {
+      start.WriteU16 (0); //not yet implemented
+    }
+
+  //
+  // Transmit power expressed as decibel distance from max power
+  // set at factory calibration (0 is max power).
+  //
+  if (m_present & RADIOTAP_DB_TX_ATTENUATION) // bit 9
+    {
+      start.WriteU16 (0); //not yet implemented
+    }
+
+  //
+  // Transmit power expressed as dBm (decibels from a 1 milliwatt reference).
+  // This is the absolute power level measured at the antenna port.
+  //
+  if (m_present & RADIOTAP_DBM_TX_POWER) // bit 10
+    {
+      start.WriteU8 (0); //not yet implemented
+    }
+
+  //
+  // Unitless indication of the Rx/Tx antenna for this packet.
+  // The first antenna is antenna 0.
+  //
+  if (m_present & RADIOTAP_ANTENNA) // bit 11
+    {
+      start.WriteU8 (0); //not yet implemented
+    }
+
+  //
+  // RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
+  //
+  if (m_present & RADIOTAP_DB_ANTSIGNAL) // bit 12
+    {
+      start.WriteU8 (0); //not yet implemented
+    }
+
+  //
+  // RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
+  //
+  if (m_present & RADIOTAP_DB_ANTNOISE) // bit 13
+    {
+      start.WriteU8 (0); //not yet implemented
+    }
+
+  //
+  // Properties of received frames.
+  //
+  if (m_present & RADIOTAP_RX_FLAGS) // bit 14
+    {
+      start.WriteU16 (0); //not yet implemented
+    }
+
+  //
+  // MCS field.
+  //
+  if (m_present & RADIOTAP_MCS) // bit 19
+    {
+      start.WriteU8 (m_mcsKnown);
+      start.WriteU8 (m_mcsFlags);
+      start.WriteU8 (m_mcsRate);
+    }
+
+  //
+  // A-MPDU Status, information about the received or transmitted A-MPDU.
+  //
+  if (m_present & RADIOTAP_AMPDU_STATUS) // bit 20
+    {
+      start.WriteU8 (0, m_ampduStatusPad);
+      start.WriteU32 (m_ampduStatusRef);
+      start.WriteU16 (m_ampduStatusFlags);
+      start.WriteU8 (m_ampduStatusCRC);
+      start.WriteU8 (0);
+    }
+
+  //
+  // Information about the received or transmitted VHT frame.
+  //
+  if (m_present & RADIOTAP_VHT) // bit 21
+    {
+      //not yet implemented
+      start.WriteU16 (0);
+      start.WriteU8 (0);
+      start.WriteU8 (0);
+      start.WriteU8 (0);
+      start.WriteU8 (0);
+      start.WriteU8 (0);
+      start.WriteU8 (0);
+      start.WriteU8 (0);
+      start.WriteU8 (0);
+      start.WriteU16 (0);
+    }
 }
 
 uint32_t
@@ -176,9 +298,11 @@
   //
   if (m_present & RADIOTAP_CHANNEL) // bit 3
     {
+      m_channelPad = ((2 - bytesRead % 2) % 2);
+      start.Next (m_channelPad);
       m_channelFreq = start.ReadU16 ();
       m_channelFlags = start.ReadU16 ();
-      bytesRead += 4;
+      bytesRead += (4 + m_channelPad);
     }
 
   //
@@ -187,6 +311,7 @@
   //
   if (m_present & RADIOTAP_FHSS) // bit 4
     {
+      //not yet implemented
       start.ReadU8 ();
       ++bytesRead;
     }
@@ -202,7 +327,7 @@
     }
 
   //
-  // RF noise power at the antenna, decibel difference from an arbitrary, fixed 
+  // RF noise power at the antenna, decibel difference from an arbitrary, fixed
   // reference.
   //
   if (m_present & RADIOTAP_DBM_ANTNOISE) // bit 6
@@ -211,6 +336,134 @@
       ++bytesRead;
     }
 
+  //
+  // Quality of Barker code lock.
+  //
+  if (m_present & RADIOTAP_LOCK_QUALITY) // bit 7
+    {
+      //not yet implemented
+      start.ReadU16 ();
+      bytesRead += 2;
+    }
+
+  //
+  // Transmit power expressed as unitless distance from max power
+  // set at factory calibration (0 is max power).
+  //
+  if (m_present & RADIOTAP_TX_ATTENUATION) // bit 8
+    {
+      //not yet implemented
+      start.ReadU16 ();
+      bytesRead += 2;
+    }
+
+  //
+  // Transmit power expressed as decibel distance from max power
+  // set at factory calibration (0 is max power).
+  //
+  if (m_present & RADIOTAP_DB_TX_ATTENUATION) // bit 9
+    {
+      //not yet implemented
+      start.ReadU16 ();
+      bytesRead += 2;
+    }
+
+  //
+  // Transmit power expressed as dBm (decibels from a 1 milliwatt reference).
+  // This is the absolute power level measured at the antenna port.
+  //
+  if (m_present & RADIOTAP_DBM_TX_POWER) // bit 10
+    {
+      //not yet implemented
+      start.ReadU8 ();
+      ++bytesRead;
+    }
+
+  //
+  // Unitless indication of the Rx/Tx antenna for this packet.
+  // The first antenna is antenna 0.
+  //
+  if (m_present & RADIOTAP_ANTENNA) // bit 11
+    {
+      //not yet implemented
+      start.ReadU8 ();
+      ++bytesRead;
+    }
+
+  //
+  // RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
+  //
+  if (m_present & RADIOTAP_DB_ANTSIGNAL) // bit 12
+    {
+      //not yet implemented
+      start.ReadU8 ();
+      ++bytesRead;
+    }
+
+  //
+  // RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
+  //
+  if (m_present & RADIOTAP_DB_ANTNOISE) // bit 13
+    {
+      //not yet implemented
+      start.ReadU8 ();
+      ++bytesRead;
+    }
+
+  //
+  // Properties of received frames.
+  //
+  if (m_present & RADIOTAP_RX_FLAGS) // bit 14
+    {
+      //not yet implemented
+      start.ReadU16 ();
+      bytesRead += 2;
+    }
+
+  //
+  // MCS field.
+  //
+  if (m_present & RADIOTAP_MCS) // bit 19
+    {
+      m_mcsKnown = start.ReadU8 ();
+      m_mcsFlags = start.ReadU8 ();
+      m_mcsRate = start.ReadU8 ();
+      bytesRead += 3;
+    }
+
+  //
+  // A-MPDU Status, information about the received or transmitted A-MPDU.
+  //
+  if (m_present & RADIOTAP_AMPDU_STATUS) // bit 20
+    {
+      m_ampduStatusPad = ((4 - bytesRead % 4) % 4);
+      start.Next (m_ampduStatusPad);
+      m_ampduStatusRef = start.ReadU32 ();
+      m_ampduStatusFlags = start.ReadU16 ();
+      m_ampduStatusCRC = start.ReadU8 ();
+      start.ReadU8 ();
+      bytesRead += (8 + m_ampduStatusPad);
+    }
+
+  //
+  // Information about the received or transmitted VHT frame.
+  //
+  if (m_present & RADIOTAP_VHT) // bit 21
+    {
+      //not yet implemented
+      start.ReadU16 ();
+      start.ReadU8 ();
+      start.ReadU8 ();
+      start.ReadU8 ();
+      start.ReadU8 ();
+      start.ReadU8 ();
+      start.ReadU8 ();
+      start.ReadU8 ();
+      start.ReadU8 ();
+      start.ReadU16 ();
+      bytesRead += 12;
+    }
+
   NS_ASSERT_MSG (m_length == bytesRead, "RadiotapHeader::Deserialize(): expected and actual lengths inconsistent");
   return bytesRead;
 }
@@ -225,7 +478,11 @@
      << " freq=" << m_channelFreq
      << " chflags=" << std::hex << (uint32_t)m_channelFlags << std::dec
      << " signal=" << (int16_t) m_antennaSignal
-     << " noise=" << (int16_t) m_antennaNoise;
+     << " noise=" << (int16_t) m_antennaNoise
+     << " mcsKnown=" << m_mcsKnown
+     << " mcsFlags=" << m_mcsFlags
+     << " mcsRate=" << m_mcsRate
+     << " ampduStatusFlags=" << (int16_t) m_ampduStatusFlags;
 }
 
 void
@@ -250,7 +507,7 @@
   return m_tsft;
 }
 
-void 
+void
 RadiotapHeader::SetFrameFlags (uint8_t flags)
 {
   NS_LOG_FUNCTION (this << static_cast<uint32_t> (flags));
@@ -272,7 +529,7 @@
   return m_flags;
 }
 
-void 
+void
 RadiotapHeader::SetRate (uint8_t rate)
 {
   NS_LOG_FUNCTION (this << static_cast<uint32_t> (rate));
@@ -294,7 +551,7 @@
   return m_rate;
 }
 
-void 
+void
 RadiotapHeader::SetChannelFrequencyAndFlags (uint16_t frequency, uint16_t flags)
 {
   NS_LOG_FUNCTION (this << frequency << flags);
@@ -303,28 +560,29 @@
 
   if (!(m_present & RADIOTAP_CHANNEL))
     {
+      m_channelPad = ((2 - m_length % 2) % 2);
       m_present |= RADIOTAP_CHANNEL;
-      m_length += 4;
+      m_length += (4 + m_channelPad);
     }
 
   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
 }
 
-uint16_t 
+uint16_t
 RadiotapHeader::GetChannelFrequency (void) const
 {
   NS_LOG_FUNCTION (this);
   return m_channelFreq;
 }
 
-uint16_t 
+uint16_t
 RadiotapHeader::GetChannelFlags (void) const
 {
   NS_LOG_FUNCTION (this);
   return m_channelFlags;
 }
 
-void 
+void
 RadiotapHeader::SetAntennaSignalPower (double signal)
 {
   NS_LOG_FUNCTION (this << signal);
@@ -383,11 +641,79 @@
   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
 }
 
-uint8_t 
+uint8_t
 RadiotapHeader::GetAntennaNoisePower (void) const
 {
   NS_LOG_FUNCTION (this);
   return m_antennaNoise;
 }
 
+void
+RadiotapHeader::SetMcsFields (uint8_t known, uint8_t flags, uint8_t mcs)
+{
+  NS_LOG_FUNCTION (this << known << flags << mcs);
+  m_mcsKnown = known;
+  m_mcsFlags = flags;
+  m_mcsRate = mcs;
+  if (!(m_present & RADIOTAP_MCS))
+    {
+      m_present |= RADIOTAP_MCS;
+      m_length += 3;
+    }
+
+  NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
+}
+
+uint8_t
+RadiotapHeader::GetMcsKnown () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_mcsKnown;
+}
+
+uint8_t
+RadiotapHeader::GetMcsFlags () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_mcsFlags;
+}
+
+uint8_t
+RadiotapHeader::GetMcsRate () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_mcsRate;
+}
+
+void
+RadiotapHeader::SetAmpduStatus (uint32_t referenceNumber, uint16_t flags, uint8_t crc)
+{
+  NS_LOG_FUNCTION (this << referenceNumber << flags);
+  m_ampduStatusRef = referenceNumber;
+  m_ampduStatusFlags = flags;
+  m_ampduStatusCRC = crc;
+  if (!(m_present & RADIOTAP_AMPDU_STATUS))
+    {
+      m_ampduStatusPad = ((4 - m_length % 4) % 4);
+      m_present |= RADIOTAP_AMPDU_STATUS;
+      m_length += (8 + m_ampduStatusPad);
+    }
+
+  NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
+}
+
+uint32_t
+RadiotapHeader::GetAmpduStatusRef () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_ampduStatusRef;
+}
+
+uint16_t
+RadiotapHeader::GetAmpduStatusFlags () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_ampduStatusFlags;
+}
+
 } // namespace ns3
--- a/src/network/utils/radiotap-header.h	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/network/utils/radiotap-header.h	Wed Jul 08 23:44:17 2015 +0200
@@ -3,7 +3,7 @@
  * Copyright (c) 2009 CTTC
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as 
+ * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation;
  *
  * This program is distributed in the hope that it will be useful,
@@ -15,40 +15,30 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Include., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Author: Nicola Baldo <nbaldo@cttc.es>
+ * Authors: Nicola Baldo <nbaldo@cttc.es>
+ *          Sébastien Deronne <sebastien.deronne@gmail.com>
  */
 
 #ifndef RADIOTAP_HEADER_H
 #define RADIOTAP_HEADER_H
 
 
-#include <ns3/header.h> 
+#include <ns3/header.h>
 
 namespace ns3 {
 
 /**
  * @brief Radiotap header implementation
  *
- * Radiotap is a de facto standard for 802.11 frame injection and reception. 
- * The radiotap header format is a mechanism to supply additional information 
- * about frames, from the driver to userspace applications such as libpcap, and 
- * from a userspace application to the driver for transmission. 
- *
- * @warning the radiotap header specification says that the fields included in
- * the header should be aligned to their natural size (e.g., 16-bit fields
- * aligned to 16-bit boundaries, 32-bit fields aligned to 32-bit boundaries, 
- * and so on.  This implementation does not enforce this.  However, the radiotap
- * specification enforces an order in which fields have to appear (if they 
- * appear), and this ordering is such that, provided you don't leave gaps, all
- * fields will end up aligned without the need of inserting padding space.  By 
- * the term "gap" I mean not using a field which would appear between two used 
- * fields.  Moral: don't leave gaps, or if you do be careful about how you
- * do it.
+ * Radiotap is a de facto standard for 802.11 frame injection and reception.
+ * The radiotap header format is a mechanism to supply additional information
+ * about frames, from the driver to userspace applications such as libpcap, and
+ * from a userspace application to the driver for transmission.
  */
 class RadiotapHeader : public Header
 {
 public:
-  RadiotapHeader();
+  RadiotapHeader ();
   /**
    * \brief Get the type ID.
    * \return the object TypeId
@@ -58,7 +48,7 @@
 
   /**
    * This method is used by Packet::AddHeader to store the header into the byte
-   * buffer of a packet.  This method returns the number of bytes which are 
+   * buffer of a packet.  This method returns the number of bytes which are
    * needed to store the header data during a Serialize.
    *
    * @returns The expected size of the header.
@@ -67,7 +57,7 @@
 
   /**
    * This method is used by Packet::AddHeader to store the header into the byte
-   * buffer of a packet.  The data written is expected to match bit-for-bit the 
+   * buffer of a packet.  The data written is expected to match bit-for-bit the
    * representation of this header in a real network.
    *
    * @param start An iterator which points to where the header should
@@ -76,8 +66,8 @@
   virtual void Serialize (Buffer::Iterator start) const;
 
   /**
-   * This method is used by Packet::RemoveHeader to re-create a header from the 
-   * byte buffer of a packet.  The data read is expected to match bit-for-bit 
+   * This method is used by Packet::RemoveHeader to re-create a header from the
+   * byte buffer of a packet.  The data read is expected to match bit-for-bit
    * the representation of this header in real networks.
    *
    * @param start An iterator which points to where the header should
@@ -87,12 +77,12 @@
   virtual uint32_t Deserialize (Buffer::Iterator start);
 
   /**
-   * This method is used by Packet::Print to print the content of the header as 
-   * ascii data to a C++ output stream.  Although the header is free to format 
+   * This method is used by Packet::Print to print the content of the header as
+   * ascii data to a C++ output stream.  Although the header is free to format
    * its output as it wishes, it is recommended to follow a few rules to integrate
-   * with the packet pretty printer: start with flags, small field 
-   * values located between a pair of parens. Values should be separated 
-   * by whitespace. Follow the parens with the important fields, 
+   * with the packet pretty printer: start with flags, small field
+   * values located between a pair of parens. Values should be separated
+   * by whitespace. Follow the parens with the important fields,
    * separated by whitespace.
    *
    * eg: (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
@@ -103,9 +93,9 @@
 
   /**
    * @brief Set the Time Synchronization Function Timer (TSFT) value.  Valid for
-   * received frames only. 
+   * received frames only.
    *
-   * @param tsft Value in microseconds of the MAC's 64-bit 802.11 Time 
+   * @param tsft Value in microseconds of the MAC's 64-bit 802.11 Time
    *             Synchronization Function timer when the first bit of the MPDU
    *             arrived at the MAC.
    */
@@ -113,15 +103,16 @@
 
   /**
    * @brief Get the Time Synchronization Function Timer (TSFT) value.  Valid for
-   * received frames only. 
+   * received frames only.
    *
-   * @returns The value in microseconds of the MAC's 64-bit 802.11 Time 
+   * @returns The value in microseconds of the MAC's 64-bit 802.11 Time
    *          Synchronization Function timer when the first bit of the MPDU
    *          arrived at the MAC.
    */
   uint64_t GetTsft (void) const;
 
-  enum {
+  enum
+  {
     FRAME_FLAG_NONE           = 0x00, /**< No flags set */
     FRAME_FLAG_CFP            = 0x01, /**< Frame sent/received during CFP */
     FRAME_FLAG_SHORT_PREAMBLE = 0x02, /**< Frame sent/received with short preamble */
@@ -158,7 +149,8 @@
    */
   uint8_t GetRate (void) const;
 
-  enum {
+  enum
+  {
     CHANNEL_FLAG_NONE          = 0x0000, /**< No flags set */
     CHANNEL_FLAG_TURBO         = 0x0010, /**< Turbo Channel */
     CHANNEL_FLAG_CCK           = 0x0020, /**< CCK channel */
@@ -193,7 +185,7 @@
 
   /**
    * @brief Set the RF signal power at the antenna as a decibel difference
-   * from an arbitrary, fixed reference. 
+   * from an arbitrary, fixed reference.
    *
    * @param signal The RF signal power at the antenna as a decibel difference
    *               from an arbitrary, fixed reference;
@@ -202,33 +194,122 @@
 
   /**
    * @brief Get the RF signal power at the antenna as a decibel difference
-   * from an arbitrary, fixed reference. 
+   * from an arbitrary, fixed reference.
    *
    * @returns The RF signal power at the antenna as a decibel difference
-   *          from an arbitrary, fixed reference. 
+   *          from an arbitrary, fixed reference.
    */
   uint8_t GetAntennaSignalPower (void) const;
 
   /**
    * @brief Set the RF noise power at the antenna as a decibel difference
-   * from an arbitrary, fixed reference. 
+   * from an arbitrary, fixed reference.
    *
    * @param noise The RF noise power at the antenna as a decibel difference
-   *              from an arbitrary, fixed reference. 
+   *              from an arbitrary, fixed reference.
    */
   void SetAntennaNoisePower (double noise);
 
   /**
    * @brief Get the RF noise power at the antenna as a decibel difference
-   * from an arbitrary, fixed reference. 
+   * from an arbitrary, fixed reference.
    *
    * @returns The RF noise power at the antenna as a decibel difference
-   *          from an arbitrary, fixed reference. 
+   *          from an arbitrary, fixed reference.
    */
   uint8_t GetAntennaNoisePower (void) const;
 
+  enum
+  {
+    MCS_KNOWN_NONE           = 0x00, /**< No flags set */
+    MCS_KNOWN_BANDWIDTH      = 0x01, /**< Bandwidth */
+    MCS_KNOWN_INDEX          = 0x02, /**< MCS index known */
+    MCS_KNOWN_GUARD_INTERVAL = 0x04, /**< Guard interval */
+    MCS_KNOWN_HT_FORMAT      = 0x08, /**< HT format */
+    MCS_KNOWN_FEC_TYPE       = 0x10, /**< FEC type */
+    MCS_KNOWN_STBC           = 0x20, /**< STBC known */
+    MCS_KNOWN_NESS           = 0x40, /**< Ness known (Number of extension spatial streams) */
+    MCS_KNOWN_NESS_BIT_1     = 0x80, /**< Ness data - bit 1 (MSB) of Number of extension spatial streams */
+  };
+
+  enum
+  {
+    MCS_FLAGS_NONE           = 0x00, /**< Default: 20 MHz, long guard interval, mixed HT format and BCC FEC type */
+    MCS_FLAGS_BANDWIDTH_40   = 0x01, /**< 40 MHz */
+    MCS_FLAGS_BANDWIDTH_20L  = 0x02, /**< 20L (20 MHz in lower half of 40 MHz channel) */
+    MCS_FLAGS_BANDWIDTH_20U  = 0x03, /**< 20U (20 MHz in upper half of 40 MHz channel) */
+    MCS_FLAGS_GUARD_INTERVAL = 0x04, /**< Short guard interval */
+    MCS_FLAGS_HT_GREENFIELD  = 0x08, /**< Greenfield HT format */
+    MCS_FLAGS_FEC_TYPE       = 0x10, /**< LDPC FEC type */
+    MCS_FLAGS_STBC_STREAMS   = 0x60, /**< STBC enabled */
+    MCS_FLAGS_NESS_BIT_0     = 0x80, /**< Ness - bit 0 (LSB) of Number of extension spatial streams */
+  };
+
+  /**
+   * @brief Set the MCS fields
+   *
+   * @param known The kwown flags.
+   * @param flags The flags to set.
+   * @param mcs The MCS index value.
+   */
+  void SetMcsFields (uint8_t known, uint8_t flags, uint8_t mcs);
+
+  /**
+   * @brief Get the MCS known bitmap.
+   *
+   * @returns The MCS known bitmap.
+   */
+  uint8_t GetMcsKnown (void) const;
+  /**
+   * @brief Get the MCS flags.
+   *
+   * @returns The MCS flags.
+   */
+  uint8_t GetMcsFlags (void) const;
+  /**
+   * @brief Get the MCS index value.
+   *
+   * @returns The MCS index value.
+   */
+  uint8_t GetMcsRate (void) const;
+
+  enum
+  {
+    A_MPDU_STATUS_NONE                = 0x00, /**< No flags set */
+    A_MPDU_STATUS_REPORT_ZERO_LENGTH  = 0x01, /**< Driver reports 0-length subframes */
+    A_MPDU_STATUS_IS_ZERO_LENGTH      = 0x02, /**< Frame is 0-length subframe (valid only if 0x0001 is set) */
+    A_MPDU_STATUS_LAST_KNOWN          = 0x04, /**< Last subframe is known (should be set for all subframes in an A-MPDU) */
+    A_MPDU_STATUS_LAST                = 0x08, /**< This frame is the last subframe */
+    A_MPDU_STATUS_DELIMITER_CRC_ERROR = 0x10, /**< Delimiter CRC error */
+    A_MPDU_STATUS_DELIMITER_CRC_KNOWN = 0x20  /**< Delimiter CRC value known: the delimiter CRC value field is valid */
+  };
+
+  /**
+   * @brief Set the A-MPDU status fields
+   *
+   * @param referenceNumber The A-MPDU reference number to identify all subframes belonging to the same A-MPDU.
+   * @param flags The flags to set.
+   * @param crc The CRC value value.
+   */
+  void SetAmpduStatus (uint32_t referenceNumber, uint16_t flags, uint8_t crc);
+
+  /**
+   * @brief Get the A-MPDU reference number.
+   *
+   * @returns The A-MPDU reference number.
+   */
+  uint32_t GetAmpduStatusRef (void) const;
+  /**
+   * @brief Get the A-MPDU status flags.
+   *
+   * @returns The A-MPDU status flags.
+   */
+  uint16_t GetAmpduStatusFlags (void) const;
+
+
 private:
-  enum {
+  enum
+  {
     RADIOTAP_TSFT              = 0x00000001,
     RADIOTAP_FLAGS             = 0x00000002,
     RADIOTAP_RATE              = 0x00000004,
@@ -239,23 +320,37 @@
     RADIOTAP_LOCK_QUALITY      = 0x00000080,
     RADIOTAP_TX_ATTENUATION    = 0x00000100,
     RADIOTAP_DB_TX_ATTENUATION = 0x00000200,
-    RADIOTAP_DBM_TX_POWER      = 0x00000200,
-    RADIOTAP_ANTENNA           = 0x00000400,
-    RADIOTAP_DB_ANTSIGNAL      = 0x00000800,
-    RADIOTAP_DB_ANTNOISE       = 0x00001000,
+    RADIOTAP_DBM_TX_POWER      = 0x00000400,
+    RADIOTAP_ANTENNA           = 0x00000800,
+    RADIOTAP_DB_ANTSIGNAL      = 0x00001000,
+    RADIOTAP_DB_ANTNOISE       = 0x00002000,
+    RADIOTAP_RX_FLAGS          = 0x00004000,
+    RADIOTAP_MCS               = 0x00080000,
+    RADIOTAP_AMPDU_STATUS      = 0x00100000,
+    RADIOTAP_VHT               = 0x00200000,
     RADIOTAP_EXT               = 0x10000000
   };
- 
+
   uint16_t m_length;        //!< entire length of radiotap data + header
   uint32_t m_present;       //!< bits describing which fields follow header
 
   uint64_t m_tsft;          //!< Time Synchronization Function Timer (when the first bit of the MPDU arrived at the MAC)
   uint8_t m_flags;          //!< Properties of transmitted and received frames.
   uint8_t m_rate;           //!< TX/RX data rate in units of 500 kbps
+  uint8_t m_channelPad;     //!< Tx/Rx channel padding.
   uint16_t m_channelFreq;   //!< Tx/Rx frequency in MHz.
   uint16_t m_channelFlags;  //!< Tx/Rx channel flags.
   int8_t m_antennaSignal;   //!< RF signal power at the antenna, dB difference from an arbitrary, fixed reference.
   int8_t m_antennaNoise;    //!< RF noise power at the antenna, dB difference from an arbitrary, fixed reference.
+
+  uint8_t m_mcsKnown; //!< MCS Flags, known information field.
+  uint8_t m_mcsFlags; //!< MCS Flags, flags field.
+  uint8_t m_mcsRate;  //!< MCS Flags, mcs rate index.
+
+  uint8_t m_ampduStatusPad;       //!< A-MPDU Status Flags, padding before A-MPDU Status Field.
+  uint32_t m_ampduStatusRef;      //!< A-MPDU Status Flags, reference number.
+  uint16_t m_ampduStatusFlags;    //!< A-MPDU Status Flags, information about the received A-MPDU.
+  uint8_t m_ampduStatusCRC;       //!< A-MPDU Status Flags, delimiter CRC value.
 };
 
 } // namespace ns3
--- a/src/wave/helper/wave-helper.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wave/helper/wave-helper.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -24,6 +24,7 @@
 #include "ns3/config.h"
 #include "ns3/names.h"
 #include "ns3/abort.h"
+#include "ns3/ampdu-subframe-header.h"
 #include "ns3/wave-net-device.h"
 #include "ns3/minstrel-wifi-manager.h"
 #include "ns3/radiotap-header.h"
@@ -92,8 +93,9 @@
   uint16_t             channelFreqMhz,
   uint16_t             channelNumber,
   uint32_t             rate,
-  bool                 isShortPreamble,
-  WifiTxVector         txvector)
+  WifiPreamble         preamble,
+  WifiTxVector         txvector,
+  struct mpduInfo      aMpdu)
 {
   uint32_t dlt = file->GetDataLinkType ();
 
@@ -114,29 +116,29 @@
         uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
         header.SetTsft (Simulator::Now ().GetMicroSeconds ());
 
-        // Our capture includes the FCS, so we set the flag to say so.
+        //Our capture includes the FCS, so we set the flag to say so.
         frameFlags |= RadiotapHeader::FRAME_FLAG_FCS_INCLUDED;
 
-        if (isShortPreamble)
+        if (preamble == WIFI_PREAMBLE_SHORT)
           {
             frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE;
           }
-          
+
         if (txvector.IsShortGuardInterval ())
           {
             frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_GUARD;
           }
-          
+
         header.SetFrameFlags (frameFlags);
         header.SetRate (rate);
 
         uint16_t channelFlags = 0;
         switch (rate)
           {
-          case 2:  // 1Mbps
-          case 4:  // 2Mbps
-          case 10: // 5Mbps
-          case 22: // 11Mbps
+          case 2:  //1Mbps
+          case 4:  //2Mbps
+          case 10: //5Mbps
+          case 22: //11Mbps
             channelFlags |= RadiotapHeader::CHANNEL_FLAG_CCK;
             break;
 
@@ -156,6 +158,71 @@
 
         header.SetChannelFrequencyAndFlags (channelFreqMhz, channelFlags);
 
+        if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF || preamble == WIFI_PREAMBLE_NONE)
+          {
+            uint8_t mcsRate = 0;
+            uint8_t mcsKnown = RadiotapHeader::MCS_KNOWN_NONE;
+            uint8_t mcsFlags = RadiotapHeader::MCS_FLAGS_NONE;
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_INDEX;
+            mcsRate = rate - 128;
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_BANDWIDTH;
+            if (txvector.GetMode ().GetBandwidth () == 40000000)
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_BANDWIDTH_40;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_GUARD_INTERVAL;
+            if (txvector.IsShortGuardInterval ())
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_GUARD_INTERVAL;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_HT_FORMAT;
+            if (preamble == WIFI_PREAMBLE_HT_GF)
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_HT_GREENFIELD;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS;
+            if (txvector.GetNess () & 0x01) //bit 1
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
+              }
+            if (txvector.GetNess () & 0x02) //bit 2
+              {
+                mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_FEC_TYPE; //only BCC is currently supported
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_STBC;
+            if (txvector.IsStbc ())
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_STBC_STREAMS;
+              }
+
+            header.SetMcsFields (mcsKnown, mcsFlags, mcsRate);
+          }
+
+        if (txvector.IsAggregation ())
+          {
+            uint16_t ampduStatusFlags = RadiotapHeader::A_MPDU_STATUS_NONE;
+            ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_DELIMITER_CRC_KNOWN;
+            ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
+            if (aMpdu.packetType == 2)
+              {
+                ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST;
+              }
+            /* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
+            AmpduSubframeHeader hdr;
+            uint32_t extractedLength;
+            p->RemoveHeader (hdr);
+            extractedLength = hdr.GetLength ();
+            p = p->CreateFragment (0, static_cast<uint32_t> (extractedLength));
+            header.SetAmpduStatus (aMpdu.referenceNumber, ampduStatusFlags, hdr.GetCrc ());
+          }
 
         p->AddHeader (header);
         file->Write (Simulator::Now (), p);
@@ -173,10 +240,10 @@
   uint16_t             channelFreqMhz,
   uint16_t             channelNumber,
   uint32_t             rate,
-  bool                 isShortPreamble,
+  WifiPreamble         preamble,
   WifiTxVector         txvector,
-  double               signalDbm,
-  double               noiseDbm)
+  struct mpduInfo      aMpdu,
+  struct snrDbm        snr)
 {
   uint32_t dlt = file->GetDataLinkType ();
 
@@ -197,10 +264,10 @@
         uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
         header.SetTsft (Simulator::Now ().GetMicroSeconds ());
 
-        // Our capture includes the FCS, so we set the flag to say so.
+        //Our capture includes the FCS, so we set the flag to say so.
         frameFlags |= RadiotapHeader::FRAME_FLAG_FCS_INCLUDED;
 
-        if (isShortPreamble)
+        if (preamble == WIFI_PREAMBLE_SHORT)
           {
             frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE;
           }
@@ -216,10 +283,10 @@
         uint16_t channelFlags = 0;
         switch (rate)
           {
-          case 2:  // 1Mbps
-          case 4:  // 2Mbps
-          case 10: // 5Mbps
-          case 22: // 11Mbps
+          case 2:  //1Mbps
+          case 4:  //2Mbps
+          case 10: //5Mbps
+          case 22: //11Mbps
             channelFlags |= RadiotapHeader::CHANNEL_FLAG_CCK;
             break;
 
@@ -239,8 +306,74 @@
 
         header.SetChannelFrequencyAndFlags (channelFreqMhz, channelFlags);
 
-        header.SetAntennaSignalPower (signalDbm);
-        header.SetAntennaNoisePower (noiseDbm);
+        header.SetAntennaSignalPower (snr.signal);
+        header.SetAntennaNoisePower (snr.noise);
+
+        if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF || preamble == WIFI_PREAMBLE_NONE)
+          {
+            uint8_t mcsRate = 0;
+            uint8_t mcsKnown = RadiotapHeader::MCS_KNOWN_NONE;
+            uint8_t mcsFlags = RadiotapHeader::MCS_FLAGS_NONE;
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_INDEX;
+            mcsRate = rate - 128;
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_BANDWIDTH;
+            if (txvector.GetMode ().GetBandwidth () == 40000000)
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_BANDWIDTH_40;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_GUARD_INTERVAL;
+            if (txvector.IsShortGuardInterval ())
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_GUARD_INTERVAL;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_HT_FORMAT;
+            if (preamble == WIFI_PREAMBLE_HT_GF)
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_HT_GREENFIELD;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS;
+            if (txvector.GetNess () & 0x01) //bit 1
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
+              }
+            if (txvector.GetNess () & 0x02) //bit 2
+              {
+                mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_FEC_TYPE; //only BCC is currently supported
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_STBC;
+            if (txvector.IsStbc ())
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_STBC_STREAMS;
+              }
+
+            header.SetMcsFields (mcsKnown, mcsFlags, mcsRate);
+          }
+
+        if (txvector.IsAggregation ())
+          {
+            uint16_t ampduStatusFlags = 0;
+            ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_DELIMITER_CRC_KNOWN;
+            ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
+            if (aMpdu.packetType == 2)
+              {
+                ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST;
+              }
+            /* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
+            AmpduSubframeHeader hdr;
+            uint32_t extractedLength;
+            p->RemoveHeader (hdr);
+            extractedLength = hdr.GetLength ();
+            p = p->CreateFragment (0, static_cast<uint32_t> (extractedLength));
+            header.SetAmpduStatus (aMpdu.referenceNumber, ampduStatusFlags, hdr.GetCrc ());
+          }
 
         p->AddHeader (header);
         file->Write (Simulator::Now (), p);
--- a/src/wifi/examples/test-interference-helper.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/examples/test-interference-helper.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -106,7 +106,7 @@
   WifiTxVector txVector;
   txVector.SetTxPowerLevel (m_input.txPowerLevelA);
   txVector.SetMode (WifiMode (m_input.txModeA));
-  m_txA->SendPacket (p, txVector, m_input.preamble, 0);
+  m_txA->SendPacket (p, txVector, m_input.preamble, 0, 0);
 }
 
 void
@@ -116,7 +116,7 @@
   WifiTxVector txVector;
   txVector.SetTxPowerLevel (m_input.txPowerLevelB);
   txVector.SetMode (WifiMode (m_input.txModeB));
-  m_txB->SendPacket (p, txVector, m_input.preamble, 0);
+  m_txB->SendPacket (p, txVector, m_input.preamble, 0, 0);
 }
 
 InterferenceExperiment::InterferenceExperiment ()
--- a/src/wifi/examples/wifi-phy-test.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/examples/wifi-phy-test.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -74,7 +74,7 @@
   WifiTxVector txVector;
   txVector.SetTxPowerLevel (m_input.txPowerLevel);
   txVector.SetMode (mode);
-  m_tx->SendPacket (p, txVector, WIFI_PREAMBLE_LONG, 0);
+  m_tx->SendPacket (p, txVector, WIFI_PREAMBLE_LONG, 0, 0);
 }
 
 void
@@ -182,7 +182,7 @@
   WifiTxVector txVector;
   txVector.SetTxPowerLevel (m_input.txPowerLevelA);
   txVector.SetMode (WifiMode (m_input.txModeA));
-  m_txA->SendPacket (p, txVector, WIFI_PREAMBLE_LONG, 0);
+  m_txA->SendPacket (p, txVector, WIFI_PREAMBLE_LONG, 0, 0);
 }
 
 void
@@ -193,7 +193,7 @@
   WifiTxVector txVector;
   txVector.SetTxPowerLevel (m_input.txPowerLevelB);
   txVector.SetMode (WifiMode (m_input.txModeB));
-  m_txB->SendPacket (p, txVector, WIFI_PREAMBLE_LONG, 0);
+  m_txB->SendPacket (p, txVector, WIFI_PREAMBLE_LONG, 0, 0);
 }
 
 void
@@ -380,7 +380,7 @@
   cmd.AddValue ("NPackets", "The number of packets to send", input.nPackets);
   cmd.AddValue ("TargetPsr", "The psr needed to assume that we are within range", targetPsr);
   cmd.Parse (argc, argv);
-  
+
   for (input.packetSize = 10; input.packetSize < 3000; input.packetSize += 40)
     {
       double precision = 0.1;
--- a/src/wifi/helper/yans-wifi-helper.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/helper/yans-wifi-helper.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -15,7 +15,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ *          Sébastien Deronne <sebastien.deronne@gmail.com>
  */
 
 #include "ns3/trace-helper.h"
@@ -25,6 +26,7 @@
 #include "ns3/propagation-delay-model.h"
 #include "ns3/yans-wifi-channel.h"
 #include "ns3/yans-wifi-phy.h"
+#include "ns3/ampdu-subframe-header.h"
 #include "ns3/wifi-net-device.h"
 #include "ns3/radiotap-header.h"
 #include "ns3/pcap-file-wrapper.h"
@@ -253,8 +255,9 @@
   uint16_t             channelFreqMhz,
   uint16_t             channelNumber,
   uint32_t             rate,
-  bool                 isShortPreamble,
-  WifiTxVector         txvector)
+  WifiPreamble         preamble,
+  WifiTxVector         txvector,
+  struct mpduInfo      aMpdu)
 {
   uint32_t dlt = file->GetDataLinkType ();
 
@@ -278,7 +281,7 @@
         //Our capture includes the FCS, so we set the flag to say so.
         frameFlags |= RadiotapHeader::FRAME_FLAG_FCS_INCLUDED;
 
-        if (isShortPreamble)
+        if (preamble == WIFI_PREAMBLE_SHORT)
           {
             frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE;
           }
@@ -317,6 +320,72 @@
 
         header.SetChannelFrequencyAndFlags (channelFreqMhz, channelFlags);
 
+        if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF || preamble == WIFI_PREAMBLE_NONE)
+          {
+            uint8_t mcsRate = 0;
+            uint8_t mcsKnown = RadiotapHeader::MCS_KNOWN_NONE;
+            uint8_t mcsFlags = RadiotapHeader::MCS_FLAGS_NONE;
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_INDEX;
+            mcsRate = rate - 128;
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_BANDWIDTH;
+            if (txvector.GetMode ().GetBandwidth () == 40000000)
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_BANDWIDTH_40;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_GUARD_INTERVAL;
+            if (txvector.IsShortGuardInterval ())
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_GUARD_INTERVAL;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_HT_FORMAT;
+            if (preamble == WIFI_PREAMBLE_HT_GF)
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_HT_GREENFIELD;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS;
+            if (txvector.GetNess () & 0x01) //bit 1
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
+              }
+            if (txvector.GetNess () & 0x02) //bit 2
+              {
+                mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_FEC_TYPE; //only BCC is currently supported
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_STBC;
+            if (txvector.IsStbc ())
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_STBC_STREAMS;
+              }
+
+            header.SetMcsFields (mcsKnown, mcsFlags, mcsRate);
+          }
+
+        if (txvector.IsAggregation ())
+          {
+            uint16_t ampduStatusFlags = RadiotapHeader::A_MPDU_STATUS_NONE;
+            ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_DELIMITER_CRC_KNOWN;
+            ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
+            if (aMpdu.packetType == 2)
+              {
+                ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST;
+              }
+            /* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
+            AmpduSubframeHeader hdr;
+            uint32_t extractedLength;
+            p->RemoveHeader (hdr);
+            extractedLength = hdr.GetLength ();
+            p = p->CreateFragment (0, static_cast<uint32_t> (extractedLength));
+            header.SetAmpduStatus (aMpdu.referenceNumber, ampduStatusFlags, hdr.GetCrc ());
+          }
+
         p->AddHeader (header);
         file->Write (Simulator::Now (), p);
         return;
@@ -333,10 +402,10 @@
   uint16_t             channelFreqMhz,
   uint16_t             channelNumber,
   uint32_t             rate,
-  bool                 isShortPreamble,
+  WifiPreamble         preamble,
   WifiTxVector         txvector,
-  double               signalDbm,
-  double               noiseDbm)
+  struct mpduInfo      aMpdu,
+  struct snrDbm        snr)
 {
   uint32_t dlt = file->GetDataLinkType ();
 
@@ -360,7 +429,7 @@
         //Our capture includes the FCS, so we set the flag to say so.
         frameFlags |= RadiotapHeader::FRAME_FLAG_FCS_INCLUDED;
 
-        if (isShortPreamble)
+        if (preamble == WIFI_PREAMBLE_SHORT)
           {
             frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE;
           }
@@ -399,8 +468,74 @@
 
         header.SetChannelFrequencyAndFlags (channelFreqMhz, channelFlags);
 
-        header.SetAntennaSignalPower (signalDbm);
-        header.SetAntennaNoisePower (noiseDbm);
+        header.SetAntennaSignalPower (snr.signal);
+        header.SetAntennaNoisePower (snr.noise);
+
+        if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF || preamble == WIFI_PREAMBLE_NONE)
+          {
+            uint8_t mcsRate = 0;
+            uint8_t mcsKnown = RadiotapHeader::MCS_KNOWN_NONE;
+            uint8_t mcsFlags = RadiotapHeader::MCS_FLAGS_NONE;
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_INDEX;
+            mcsRate = rate - 128;
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_BANDWIDTH;
+            if (txvector.GetMode ().GetBandwidth () == 40000000)
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_BANDWIDTH_40;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_GUARD_INTERVAL;
+            if (txvector.IsShortGuardInterval ())
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_GUARD_INTERVAL;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_HT_FORMAT;
+            if (preamble == WIFI_PREAMBLE_HT_GF)
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_HT_GREENFIELD;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS;
+            if (txvector.GetNess () & 0x01) //bit 1
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
+              }
+            if (txvector.GetNess () & 0x02) //bit 2
+              {
+                mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
+              }
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_FEC_TYPE; //only BCC is currently supported
+
+            mcsKnown |= RadiotapHeader::MCS_KNOWN_STBC;
+            if (txvector.IsStbc ())
+              {
+                mcsFlags |= RadiotapHeader::MCS_FLAGS_STBC_STREAMS;
+              }
+
+            header.SetMcsFields (mcsKnown, mcsFlags, mcsRate);
+          }
+
+        if (txvector.IsAggregation ())
+          {
+            uint16_t ampduStatusFlags = 0;
+            ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_DELIMITER_CRC_KNOWN;
+            ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
+            if (aMpdu.packetType == 2)
+              {
+                ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST;
+              }
+            /* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
+            AmpduSubframeHeader hdr;
+            uint32_t extractedLength;
+            p->RemoveHeader (hdr);
+            extractedLength = hdr.GetLength ();
+            p = p->CreateFragment (0, static_cast<uint32_t> (extractedLength));
+            header.SetAmpduStatus (aMpdu.referenceNumber, ampduStatusFlags, hdr.GetCrc ());
+          }
 
         p->AddHeader (header);
         file->Write (Simulator::Now (), p);
--- a/src/wifi/model/aarf-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/aarf-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -232,7 +232,7 @@
 {
   NS_LOG_FUNCTION (this << st << size);
   AarfWifiRemoteStation *station = (AarfWifiRemoteStation *) st;
-  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
@@ -242,7 +242,7 @@
   /// \todo we could/should implement the Aarf algorithm for
   /// RTS only by picking a single rate within the BasicRateSet.
   AarfWifiRemoteStation *station = (AarfWifiRemoteStation *) st;
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 bool
--- a/src/wifi/model/aarfcd-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/aarfcd-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -304,7 +304,7 @@
 {
   NS_LOG_FUNCTION (this << st << size);
   AarfcdWifiRemoteStation *station = (AarfcdWifiRemoteStation *) st;
-  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 WifiTxVector
 AarfcdWifiManager::DoGetRtsTxVector (WifiRemoteStation *st)
@@ -313,7 +313,7 @@
   /// \todo we could/should implement the Aarf algorithm for
   /// RTS only by picking a single rate within the BasicRateSet.
   AarfcdWifiRemoteStation *station = (AarfcdWifiRemoteStation *) st;
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 bool
--- a/src/wifi/model/amrr-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/amrr-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -336,7 +336,7 @@
         }
     }
 
-  return WifiTxVector (GetSupported (station, rateIndex), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, rateIndex), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
@@ -346,7 +346,7 @@
   AmrrWifiRemoteStation *station = (AmrrWifiRemoteStation *)st;
   UpdateMode (station);
   /// \todo can we implement something smarter ?
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 bool
--- a/src/wifi/model/aparf-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/aparf-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -322,7 +322,7 @@
   NS_LOG_FUNCTION (this << st << size);
   AparfWifiRemoteStation *station = (AparfWifiRemoteStation *) st;
   CheckInit (station);
-  return WifiTxVector (GetSupported (station, station->m_rate), station->m_power, GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, station->m_rate), station->m_power, GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
@@ -332,7 +332,7 @@
   /// \todo we could/should implement the Arf algorithm for
   /// RTS only by picking a single rate within the BasicRateSet.
   AparfWifiRemoteStation *station = (AparfWifiRemoteStation *) st;
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetAggregation (station), GetStbc (station));
 }
 
 bool
--- a/src/wifi/model/arf-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/arf-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -208,7 +208,7 @@
 {
   NS_LOG_FUNCTION (this << st << size);
   ArfWifiRemoteStation *station = (ArfWifiRemoteStation *) st;
-  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
@@ -218,7 +218,7 @@
   /// \todo we could/should implement the Arf algorithm for
   /// RTS only by picking a single rate within the BasicRateSet.
   ArfWifiRemoteStation *station = (ArfWifiRemoteStation *) st;
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 bool
--- a/src/wifi/model/cara-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/cara-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -183,7 +183,7 @@
 {
   NS_LOG_FUNCTION (this << st << size);
   CaraWifiRemoteStation *station = (CaraWifiRemoteStation *) st;
-  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
@@ -192,7 +192,7 @@
   NS_LOG_FUNCTION (this << st);
   /// \todo we could/should implement the Arf algorithm for
   /// RTS only by picking a single rate within the BasicRateSet.
-  return WifiTxVector (GetSupported (st, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (st), GetShortGuardInterval (st), Min (GetNumberOfReceiveAntennas (st), GetNumberOfTransmitAntennas ()), GetNess (st), GetStbc (st));
+  return WifiTxVector (GetSupported (st, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (st), GetShortGuardInterval (st), Min (GetNumberOfReceiveAntennas (st), GetNumberOfTransmitAntennas ()), GetNess (st), GetAggregation (st), GetStbc (st));
 }
 
 bool
--- a/src/wifi/model/constant-rate-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/constant-rate-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -117,14 +117,14 @@
 ConstantRateWifiManager::DoGetDataTxVector (WifiRemoteStation *st, uint32_t size)
 {
   NS_LOG_FUNCTION (this << st << size);
-  return WifiTxVector (m_dataMode, GetDefaultTxPowerLevel (), GetLongRetryCount (st), GetShortGuardInterval (st), Min (GetNumberOfReceiveAntennas (st), GetNumberOfTransmitAntennas ()), GetNess (st), GetStbc (st));
+  return WifiTxVector (m_dataMode, GetDefaultTxPowerLevel (), GetLongRetryCount (st), GetShortGuardInterval (st), Min (GetNumberOfReceiveAntennas (st), GetNumberOfTransmitAntennas ()), GetNess (st), GetAggregation (st), GetStbc (st));
 }
 
 WifiTxVector
 ConstantRateWifiManager::DoGetRtsTxVector (WifiRemoteStation *st)
 {
   NS_LOG_FUNCTION (this << st);
-  return WifiTxVector (m_ctlMode, GetDefaultTxPowerLevel (), GetShortRetryCount (st), GetShortGuardInterval (st), Min (GetNumberOfReceiveAntennas (st), GetNumberOfTransmitAntennas ()), GetNess (st), GetStbc (st));
+  return WifiTxVector (m_ctlMode, GetDefaultTxPowerLevel (), GetShortRetryCount (st), GetShortGuardInterval (st), Min (GetNumberOfReceiveAntennas (st), GetNumberOfTransmitAntennas ()), GetNess (st), GetAggregation (st), GetStbc (st));
 }
 
 bool
--- a/src/wifi/model/ideal-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/ideal-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -169,7 +169,7 @@
           maxMode = mode;
         }
     }
-  return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
@@ -192,7 +192,7 @@
           maxMode = mode;
         }
     }
-  return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 bool
--- a/src/wifi/model/mac-low.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/mac-low.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -366,7 +366,8 @@
     m_listener (0),
     m_phyMacLowListener (0),
     m_ctsToSelfSupported (false),
-    m_receivedAtLeastOneMpdu (false)
+    m_receivedAtLeastOneMpdu (false),
+    m_mpduReferenceNumber (0)
 {
   NS_LOG_FUNCTION (this);
   m_lastNavDuration = Seconds (0);
@@ -1556,7 +1557,7 @@
                 ", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec);
   if (!m_ampdu || hdr->IsRts ())
     {
-      m_phy->SendPacket (packet, txVector, preamble, 0);
+      m_phy->SendPacket (packet, txVector, preamble, 0, 0);
     }
   else
     {
@@ -1571,6 +1572,10 @@
       AmpduTag ampdutag;
       ampdutag.SetAmpdu (true);
       Time delay = Seconds (0);
+      if (queueSize > 1)
+        {
+          txVector.SetAggregation (true);
+        }
       for (; queueSize > 0; queueSize--)
         {
           dequeuedPacket = m_aggregateQueue->Dequeue (&newHdr);
@@ -1591,11 +1596,11 @@
             {
               NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
               packetType = 1;
-              m_phy->SendPacket (newPacket, txVector, preamble, packetType);
+              m_phy->SendPacket (newPacket, txVector, preamble, packetType, m_mpduReferenceNumber);
             }
           else
             {
-              Simulator::Schedule (delay, &MacLow::SendPacket, this, newPacket, txVector, preamble, packetType);
+              Simulator::Schedule (delay, &MacLow::SendPacket, this, newPacket, txVector, preamble, packetType, m_mpduReferenceNumber);
             }
           if (queueSize > 1)
             {
@@ -1603,14 +1608,15 @@
             }
           preamble = WIFI_PREAMBLE_NONE;
         }
+      m_mpduReferenceNumber = ((m_mpduReferenceNumber + 1) % 4294967296);
     }
 }
 
 void
-MacLow::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType)
+MacLow::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, uint32_t mpduReferenceNumber)
 {
   NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
-  m_phy->SendPacket (packet, txVector, preamble, packetType);
+  m_phy->SendPacket (packet, txVector, preamble, packetType, mpduReferenceNumber);
 }
 
 void
--- a/src/wifi/model/mac-low.h	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/mac-low.h	Wed Jul 08 23:44:17 2015 +0200
@@ -886,8 +886,10 @@
    * \param hdr
    * \param txVector
    * \param preamble
+   * \param packetType
+   * \param mpduReferenceNumber
    */
-  void SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType);
+  void SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, uint32_t mpduReferenceNumber);
   /**
    * Return a TXVECTOR for the RTS frame given the destination.
    * The function consults WifiRemoteStationManager, which controls the rate
@@ -1367,6 +1369,7 @@
   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.
+  uint32_t m_mpduReferenceNumber;       //!< A-MPDU reference number to identify all subframes belonging to the same A-MPDU
 };
 
 } //namespace ns3
--- a/src/wifi/model/minstrel-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/minstrel-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -482,7 +482,7 @@
       station->m_txrate = m_nsupported / 2;
     }
   UpdateStats (station);
-  return WifiTxVector (GetSupported (station, station->m_txrate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, station->m_txrate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
@@ -491,7 +491,7 @@
   MinstrelWifiRemoteStation *station = (MinstrelWifiRemoteStation *) st;
   NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
 
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station),GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 bool
--- a/src/wifi/model/onoe-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/onoe-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -278,7 +278,7 @@
           rateIndex = station->m_txrate;
         }
     }
-  return WifiTxVector (GetSupported (station, rateIndex), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, rateIndex), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
@@ -287,7 +287,7 @@
   OnoeWifiRemoteStation *station = (OnoeWifiRemoteStation *)st;
   UpdateMode (station);
   /// \todo can we implement something smarter ?
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 bool
--- a/src/wifi/model/parf-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/parf-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -294,7 +294,7 @@
   NS_LOG_FUNCTION (this << st << size);
   ParfWifiRemoteStation *station = (ParfWifiRemoteStation *) st;
   CheckInit (station);
-  return WifiTxVector (GetSupported (station, station->m_currentRate), station->m_currentPower, GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, station->m_currentRate), station->m_currentPower, GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
@@ -304,7 +304,7 @@
   /// \todo we could/should implement the Arf algorithm for
   /// RTS only by picking a single rate within the BasicRateSet.
   ParfWifiRemoteStation *station = (ParfWifiRemoteStation *) st;
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNumberOfTransmitAntennas (station), GetAggregation (station), GetStbc (station));
 }
 
 bool
--- a/src/wifi/model/rraa-wifi-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/rraa-wifi-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -290,13 +290,13 @@
     {
       ResetCountersBasic (station);
     }
-  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetStbc (station));
+  return WifiTxVector (GetSupported (station, station->m_rate), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetShortGuardInterval (station), Min (GetNumberOfReceiveAntennas (station), GetNumberOfTransmitAntennas ()), GetNess (station), GetAggregation (station), GetStbc (station));
 }
 
 WifiTxVector
 RraaWifiManager::DoGetRtsTxVector (WifiRemoteStation *st)
 {
-  return WifiTxVector (GetSupported (st, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (st), GetShortGuardInterval (st), Min (GetNumberOfReceiveAntennas (st), GetNumberOfTransmitAntennas ()), GetNess (st), GetStbc (st));
+  return WifiTxVector (GetSupported (st, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (st), GetShortGuardInterval (st), Min (GetNumberOfReceiveAntennas (st), GetNumberOfTransmitAntennas ()), GetNess (st), GetAggregation (st), GetStbc (st));
 }
 
 bool
--- a/src/wifi/model/wifi-phy.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/wifi-phy.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -592,15 +592,15 @@
 }
 
 void
-WifiPhy::NotifyMonitorSniffRx (Ptr<const Packet> packet, uint16_t channelFreqMhz, uint16_t channelNumber, uint32_t rate, bool isShortPreamble, WifiTxVector txvector, double signalDbm, double noiseDbm)
+WifiPhy::NotifyMonitorSniffRx (Ptr<const Packet> packet, uint16_t channelFreqMhz, uint16_t channelNumber, uint32_t rate, WifiPreamble preamble, WifiTxVector txvector, struct mpduInfo aMpdu, struct snrDbm snr)
 {
-  m_phyMonitorSniffRxTrace (packet, channelFreqMhz, channelNumber, rate, isShortPreamble, txvector, signalDbm, noiseDbm);
+  m_phyMonitorSniffRxTrace (packet, channelFreqMhz, channelNumber, rate, preamble, txvector, aMpdu, snr);
 }
 
 void
-WifiPhy::NotifyMonitorSniffTx (Ptr<const Packet> packet, uint16_t channelFreqMhz, uint16_t channelNumber, uint32_t rate, bool isShortPreamble, WifiTxVector txvector)
+WifiPhy::NotifyMonitorSniffTx (Ptr<const Packet> packet, uint16_t channelFreqMhz, uint16_t channelNumber, uint32_t rate, WifiPreamble preamble, WifiTxVector txvector, struct mpduInfo aMpdu)
 {
-  m_phyMonitorSniffTxTrace (packet, channelFreqMhz, channelNumber, rate, isShortPreamble, txvector);
+  m_phyMonitorSniffTxTrace (packet, channelFreqMhz, channelNumber, rate, preamble, txvector, aMpdu);
 }
 
 
--- a/src/wifi/model/wifi-phy.h	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/wifi-phy.h	Wed Jul 08 23:44:17 2015 +0200
@@ -38,6 +38,18 @@
 class WifiChannel;
 class NetDevice;
 
+struct snrDbm
+{
+  double signal;
+  double noise;
+};
+
+struct mpduInfo
+{
+  uint8_t packetType;
+  uint32_t referenceNumber;
+};
+
 /**
  * \brief receive notifications about phy events.
  */
@@ -209,8 +221,9 @@
    *        power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels
    * \param preamble the type of preamble to use to send this packet.
    * \param packetType the type of the packet 0 is not A-MPDU, 1 is a MPDU that is part of an A-MPDU and 2 is the last MPDU in an A-MPDU
+   * \param mpduReferenceNumber the A-MPDU reference number (must be a different value for each A-MPDU but the same for each subframe within one A-MPDU)
    */
-  virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txvector, enum WifiPreamble preamble, uint8_t packetType) = 0;
+  virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txvector, enum WifiPreamble preamble, uint8_t packetType, uint32_t mpduReferenceNumber) = 0;
 
   /**
    * \param listener the new listener
@@ -997,15 +1010,15 @@
    * \param channelNumber the channel on which the packet is received
    * \param rate the PHY data rate in units of 500kbps (i.e., the same
    *        units used both for the radiotap and for the prism header)
-   * \param isShortPreamble true if short preamble is used, false otherwise
+   * \param preamble the preamble of the packet
    * \param txVector the txvector that holds rx parameters
-   * \param signalDbm signal power in dBm
-   * \param noiseDbm  noise power in dBm
+   * \param aMpdu the type of the packet (0 is not A-MPDU, 1 is a MPDU that is part of an A-MPDU and 2 is the last MPDU in an A-MPDU)
+   *        and the A-MPDU reference number (must be a different value for each A-MPDU but the same for each subframe within one A-MPDU)
+   * \param snr signal power and noise power in dBm
    */
   void NotifyMonitorSniffRx (Ptr<const Packet> packet, uint16_t channelFreqMhz,
-                             uint16_t channelNumber, uint32_t rate,
-                             bool isShortPreamble, WifiTxVector txvector,
-                             double signalDbm, double noiseDbm);
+                             uint16_t channelNumber, uint32_t rate, WifiPreamble preamble,
+                             WifiTxVector txvector, struct mpduInfo aMpdu, struct snrDbm snr);
 
   /**
    * TracedCallback signature for monitor mode receive events.
@@ -1022,15 +1035,15 @@
    * \param channelNumber the channel on which the packet is received
    * \param rate the PHY data rate in units of 500kbps (i.e., the same
    *        units used both for the radiotap and for the prism header)
-   * \param isShortPreamble true if short preamble is used, false otherwise
+   * \param preamble the preamble of the packet
    * \param txVector the txvector that holds rx parameters
-   * \param signalDbm signal power in dBm
-   * \param noiseDbm noise power in dBm
+   * \param aMpdu the type of the packet (0 is not A-MPDU, 1 is a MPDU that is part of an A-MPDU and 2 is the last MPDU in an A-MPDU)
+   *        and the A-MPDU reference number (must be a different value for each A-MPDU but the same for each subframe within one A-MPDU)
+   * \param snr signal power and noise power in dBm
    */
   typedef void (* MonitorSnifferRxCallback)(Ptr<const Packet> packet, uint16_t channelFreqMhz,
-                                            uint16_t channelNumber, uint32_t rate,
-                                            bool isShortPreamble, WifiTxVector txvector,
-                                            double signalDbm, double noiseDbm);
+                                            uint16_t channelNumber, uint32_t rate, WifiPreamble preamble,
+                                            WifiTxVector txvector, struct mpduInfo aMpdu, struct snrDbm snr);
 
   /**
    * Public method used to fire a MonitorSniffer trace for a wifi packet being transmitted.
@@ -1042,12 +1055,14 @@
    * \param channelNumber the channel on which the packet is transmitted
    * \param rate the PHY data rate in units of 500kbps (i.e., the same
    *        units used both for the radiotap and for the prism header)
-   * \param isShortPreamble true if short preamble is used, false otherwise
+   * \param preamble the preamble of the packet
    * \param txVector the txvector that holds tx parameters
+   * \param aMpdu the type of the packet (0 is not A-MPDU, 1 is a MPDU that is part of an A-MPDU and 2 is the last MPDU in an A-MPDU)
+   *        and the A-MPDU reference number (must be a different value for each A-MPDU but the same for each subframe within one A-MPDU)
    */
   void NotifyMonitorSniffTx (Ptr<const Packet> packet, uint16_t channelFreqMhz,
-                             uint16_t channelNumber, uint32_t rate,
-                             bool isShortPreamble, WifiTxVector txvector);
+                             uint16_t channelNumber, uint32_t rate, WifiPreamble preamble,
+                             WifiTxVector txvector, struct mpduInfo aMpdu);
 
   /**
    * TracedCallback signature for monitor mode transmit events.
@@ -1058,12 +1073,14 @@
    * \param channelNumber the channel on which the packet is transmitted
    * \param rate the PHY data rate in units of 500kbps (i.e., the same
    *        units used both for the radiotap and for the prism header)
-   * \param isShortPreamble true if short preamble is used, false otherwise
+   * \param preamble the preamble of the packet
    * \param txVector the txvector that holds tx parameters
+   * \param aMpdu the type of the packet (0 is not A-MPDU, 1 is a MPDU that is part of an A-MPDU and 2 is the last MPDU in an A-MPDU)
+   *        and the A-MPDU reference number (must be a different value for each A-MPDU but the same for each subframe within one A-MPDU)
    */
   typedef void (* MonitorSnifferTxCallback)(const Ptr<const Packet> packet, uint16_t channelFreqMhz,
-                                            uint16_t channelNumber, uint32_t rate,
-                                            bool isShortPreamble, WifiTxVector txvector);
+                                            uint16_t channelNumber, uint32_t rate, WifiPreamble preamble,
+                                            WifiTxVector txvector, struct mpduInfo aMpdu);
 
   /**
    * Assign a fixed random variable stream number to the random variables
@@ -1199,7 +1216,7 @@
    *
    * \see class CallBackTraceSource
    */
-  TracedCallback<Ptr<const Packet>, uint16_t, uint16_t, uint32_t, bool, WifiTxVector, double, double> m_phyMonitorSniffRxTrace;
+  TracedCallback<Ptr<const Packet>, uint16_t, uint16_t, uint32_t, WifiPreamble, WifiTxVector, struct mpduInfo, struct snrDbm> m_phyMonitorSniffRxTrace;
 
   /**
    * A trace source that emulates a wifi device in monitor mode
@@ -1211,7 +1228,7 @@
    *
    * \see class CallBackTraceSource
    */
-  TracedCallback<Ptr<const Packet>, uint16_t, uint16_t, uint32_t, bool, WifiTxVector> m_phyMonitorSniffTxTrace;
+  TracedCallback<Ptr<const Packet>, uint16_t, uint16_t, uint32_t, WifiPreamble, WifiTxVector, struct mpduInfo> m_phyMonitorSniffTxTrace;
 
   uint32_t m_totalAmpduNumSymbols; //!< Number of symbols previously transmitted for the MPDUs in an A-MPDU, used for the computation of the number of symbols needed for the last MPDU in the A-MPDU
   uint32_t m_totalAmpduSize;       //!< Total size of the previously transmitted MPDUs in an A-MPDU, used for the computation of the number of symbols needed for the last MPDU in the A-MPDU
--- a/src/wifi/model/wifi-remote-station-manager.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/wifi-remote-station-manager.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -661,6 +661,7 @@
                        m_wifiPhy->GetGuardInterval (),
                        GetNumberOfTransmitAntennas (),
                        GetNumberOfTransmitAntennas (),
+                       false,
                        false);
 }
 
@@ -1271,6 +1272,7 @@
   state->m_rx = 1;
   state->m_tx = 1;
   state->m_ness = 0;
+  state->m_aggregation = false;
   state->m_stbc = false;
   const_cast<WifiRemoteStationManager *> (this)->m_states.push_back (state);
   NS_LOG_DEBUG ("WifiRemoteStationManager::LookupState returning new state");
@@ -1488,6 +1490,12 @@
 }
 
 bool
+WifiRemoteStationManager::GetAggregation (const WifiRemoteStation *station) const
+{
+  return station->m_state->m_aggregation;
+}
+
+bool
 WifiRemoteStationManager::GetStbc (const WifiRemoteStation *station) const
 {
   return station->m_state->m_stbc;
--- a/src/wifi/model/wifi-remote-station-manager.h	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/wifi-remote-station-manager.h	Wed Jul 08 23:44:17 2015 +0200
@@ -636,6 +636,15 @@
    */
   bool GetShortGuardInterval (const WifiRemoteStation *station) const;
   /**
+   * Return whether the given station supports A-MPDU.
+   *
+   * \param station the station being queried
+   *
+   * \return true if the station supports MPDU aggregation,
+   *         false otherwise
+   */
+  bool GetAggregation (const WifiRemoteStation *station) const;
+  /**
    * Return whether the given station supports space-time block coding (STBC).
    *
    * \param station the station being queried
@@ -1049,6 +1058,7 @@
   uint32_t m_tx;              //!< Number of TX antennas of the remote station
   uint32_t m_ness;            //!< Number of streams in beamforming of the remote station
   bool m_stbc;                //!< Flag if STBC is used by the remote station
+  bool m_aggregation;         //!< Flag if MPDU aggregation is used by the remote station
   bool m_greenfield;          //!< Flag if green field is used by the remote station
 };
 
--- a/src/wifi/model/wifi-tx-vector.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/wifi-tx-vector.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -29,6 +29,7 @@
     m_shortGuardInterval (false),
     m_nss (1),
     m_ness (0),
+    m_aggregation (false),
     m_stbc (false),
     m_modeInitialized (false),
     m_txPowerLevelInitialized (false)
@@ -36,13 +37,15 @@
 }
 
 WifiTxVector::WifiTxVector (WifiMode mode, uint8_t powerLevel, uint8_t retries,
-                            bool shortGuardInterval, uint8_t nss, uint8_t ness, bool stbc)
+                            bool shortGuardInterval, uint8_t nss, uint8_t ness,
+                            bool aggregation, bool stbc)
   : m_mode (mode),
     m_txPowerLevel (powerLevel),
     m_retries (retries),
     m_shortGuardInterval (shortGuardInterval),
     m_nss (nss),
     m_ness (ness),
+    m_aggregation (aggregation),
     m_stbc (stbc),
     m_modeInitialized (true),
     m_txPowerLevelInitialized (true)
@@ -94,6 +97,12 @@
 }
 
 bool
+WifiTxVector::IsAggregation (void) const
+{
+  return m_aggregation;
+}
+
+bool
 WifiTxVector::IsStbc (void) const
 {
   return m_stbc;
@@ -138,6 +147,12 @@
 }
 
 void
+WifiTxVector::SetAggregation (bool aggregation)
+{
+  m_aggregation = aggregation;
+}
+
+void
 WifiTxVector::SetStbc (bool stbc)
 {
   m_stbc = stbc;
@@ -151,6 +166,7 @@
     " Short GI: " << v.IsShortGuardInterval () <<
     " Nss: " << (uint32_t)v.GetNss () <<
     " Ness: " << (uint32_t)v.GetNess () <<
+    " MPDU aggregation" << v.IsAggregation () <<
     " STBC: " << v.IsStbc ();
   return os;
 }
--- a/src/wifi/model/wifi-tx-vector.h	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/wifi-tx-vector.h	Wed Jul 08 23:44:17 2015 +0200
@@ -73,7 +73,14 @@
    * \param ness the number of extension spatial streams (NESS)
    * \param stbc enable or disable STBC
    */
-  WifiTxVector (WifiMode mode, uint8_t powerLevel, uint8_t retries, bool shortGuardInterval, uint8_t nss, uint8_t ness, bool stbc);
+  WifiTxVector (WifiMode mode,
+                uint8_t powerLevel,
+                uint8_t retries,
+                bool shortGuardInterval,
+                uint8_t nss,
+                uint8_t ness,
+                bool aggregation,
+                bool stbc);
   /**
    * \returns the txvector payload mode
    */
@@ -135,6 +142,18 @@
    */
   void SetNess (uint8_t ness);
   /**
+   * Checks whether the PSDU contains A-MPDU.
+   *  \returns true if this PSDU has A-MPDU aggregation,
+   *           false otherwise.
+   */
+  bool IsAggregation (void) const;
+  /**
+   * Sets if PSDU contains A-MPDU.
+   *
+   * \param aggregated whether the PSDU contains A-MPDU or not.
+   */
+  void SetAggregation (bool aggregation);
+  /**
    * Check if STBC is used or not
    *
    * \returns true if STBC is used,
@@ -162,6 +181,7 @@
   bool     m_shortGuardInterval; /**< true if short GI is going to be used */
   uint8_t  m_nss;                /**< number of streams */
   uint8_t  m_ness;               /**< number of streams in beamforming */
+  bool     m_aggregation;        /** Flag whether the PSDU contains A-MPDU. */
   bool     m_stbc;               /**< STBC used or not */
 
   bool     m_modeInitialized;         //*< Internal initialization flag */
--- a/src/wifi/model/yans-wifi-channel.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/yans-wifi-channel.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -27,7 +27,6 @@
 #include "ns3/pointer.h"
 #include "ns3/object-factory.h"
 #include "yans-wifi-channel.h"
-#include "yans-wifi-phy.h"
 #include "ns3/propagation-loss-model.h"
 #include "ns3/propagation-delay-model.h"
 
@@ -80,7 +79,7 @@
 
 void
 YansWifiChannel::Send (Ptr<YansWifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
-                       WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, Time duration) const
+                       WifiTxVector txVector, WifiPreamble preamble, struct mpduInfo aMpdu, Time duration) const
 {
   Ptr<MobilityModel> senderMobility = sender->GetMobility ()->GetObject<MobilityModel> ();
   NS_ASSERT (senderMobility != 0);
@@ -112,24 +111,24 @@
               dstNode = dstNetDevice->GetObject<NetDevice> ()->GetNode ()->GetId ();
             }
 
-          double *atts = new double[3];
-          *atts = rxPowerDbm;
-          *(atts + 1) = packetType;
-          *(atts + 2) = duration.GetNanoSeconds ();
+          struct Parameters parameters;
+          parameters.rxPowerDbm = rxPowerDbm;
+          parameters.aMpdu = aMpdu;
+          parameters.duration = duration;
+          parameters.txVector = txVector;
+          parameters.preamble = preamble;
 
           Simulator::ScheduleWithContext (dstNode,
                                           delay, &YansWifiChannel::Receive, this,
-                                          j, copy, atts, txVector, preamble);
+                                          j, copy, parameters);
         }
     }
 }
 
 void
-YansWifiChannel::Receive (uint32_t i, Ptr<Packet> packet, double *atts,
-                          WifiTxVector txVector, WifiPreamble preamble) const
+YansWifiChannel::Receive (uint32_t i, Ptr<Packet> packet, struct Parameters parameters) const
 {
-  m_phyList[i]->StartReceivePreambleAndHeader (packet, *atts, txVector, preamble, *(atts + 1), NanoSeconds (*(atts + 2)));
-  delete[] atts;
+  m_phyList[i]->StartReceivePreambleAndHeader (packet, parameters.rxPowerDbm, parameters.txVector, parameters.preamble, parameters.aMpdu, parameters.duration);
 }
 
 uint32_t
--- a/src/wifi/model/yans-wifi-channel.h	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/yans-wifi-channel.h	Wed Jul 08 23:44:17 2015 +0200
@@ -28,6 +28,7 @@
 #include "wifi-mode.h"
 #include "wifi-preamble.h"
 #include "wifi-tx-vector.h"
+#include "yans-wifi-phy.h"
 #include "ns3/nstime.h"
 
 namespace ns3 {
@@ -35,7 +36,15 @@
 class NetDevice;
 class PropagationLossModel;
 class PropagationDelayModel;
-class YansWifiPhy;
+
+struct Parameters
+{
+  double rxPowerDbm;
+  struct mpduInfo aMpdu;
+  Time duration;
+  WifiTxVector txVector;
+  WifiPreamble preamble;
+};
 
 /**
  * \brief A Yans wifi channel
@@ -83,7 +92,8 @@
    * \param txPowerDbm the tx power associated to the packet
    * \param txVector the TXVECTOR associated to the packet
    * \param preamble the preamble associated to the packet
-   * \param packetType the type of packet, used for A-MPDU to say whether it's the last MPDU or not
+   * \param aMpdu the type of the packet (0 is not A-MPDU, 1 is a MPDU that is part of an A-MPDU and 2 is the last MPDU in an A-MPDU)
+   *        and the A-MPDU reference number (must be a different value for each A-MPDU but the same for each subframe within one A-MPDU)
    * \param duration the transmission duration associated to the packet
    *
    * This method should not be invoked by normal users. It is
@@ -92,7 +102,7 @@
    * e.g. PHYs that are operating on the same channel.
    */
   void Send (Ptr<YansWifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
-             WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, Time duration) const;
+             WifiTxVector txVector, WifiPreamble preamble, struct mpduInfo aMpdu, Time duration) const;
 
   /**
    * Assign a fixed random variable stream number to the random variables
@@ -111,6 +121,7 @@
    * A vector of pointers to YansWifiPhy.
    */
   typedef std::vector<Ptr<YansWifiPhy> > PhyList;
+
   /**
    * This method is scheduled by Send for each associated YansWifiPhy.
    * The method then calls the corresponding YansWifiPhy that the first
@@ -122,9 +133,7 @@
    * \param txVector the TXVECTOR of the packet
    * \param preamble the type of preamble being used to send the packet
    */
-  void Receive (uint32_t i, Ptr<Packet> packet, double *atts,
-                WifiTxVector txVector, WifiPreamble preamble) const;
-
+  void Receive (uint32_t i, Ptr<Packet> packet, struct Parameters parameters) const;
 
   PhyList m_phyList;                   //!< List of YansWifiPhys connected to this YansWifiChannel
   Ptr<PropagationLossModel> m_loss;    //!< Propagation loss model
--- a/src/wifi/model/yans-wifi-phy.cc	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/yans-wifi-phy.cc	Wed Jul 08 23:44:17 2015 +0200
@@ -562,11 +562,11 @@
                                             double rxPowerDbm,
                                             WifiTxVector txVector,
                                             enum WifiPreamble preamble,
-                                            uint8_t packetType, Time rxDuration)
+                                            struct mpduInfo aMpdu, Time rxDuration)
 {
   //This function should be later split to check separately wether plcp preamble and plcp header can be successfully received.
   //Note: plcp preamble reception is not yet modeled.
-  NS_LOG_FUNCTION (this << packet << rxPowerDbm << txVector.GetMode () << preamble << (uint32_t)packetType);
+  NS_LOG_FUNCTION (this << packet << rxPowerDbm << txVector.GetMode () << preamble << (uint32_t)aMpdu.packetType);
   AmpduTag ampduTag;
   rxPowerDbm += m_rxGainDb;
   double rxPowerW = DbmToW (rxPowerDbm);
@@ -674,12 +674,12 @@
             {
               NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
               m_endPlcpRxEvent = Simulator::Schedule (preambleAndHeaderDuration, &YansWifiPhy::StartReceivePacket, this,
-                                                      packet, txVector, preamble, packetType, event);
+                                                      packet, txVector, preamble, aMpdu, event);
             }
 
           NS_ASSERT (m_endRxEvent.IsExpired ());
           m_endRxEvent = Simulator::Schedule (rxDuration, &YansWifiPhy::EndReceive, this,
-                                              packet, preamble, packetType, event);
+                                              packet, preamble, aMpdu, event);
         }
       else
         {
@@ -716,10 +716,10 @@
 YansWifiPhy::StartReceivePacket (Ptr<Packet> packet,
                                  WifiTxVector txVector,
                                  enum WifiPreamble preamble,
-                                 uint8_t packetType,
+                                 struct mpduInfo aMpdu,
                                  Ptr<InterferenceHelper::Event> event)
 {
-  NS_LOG_FUNCTION (this << packet << txVector.GetMode () << preamble << (uint32_t)packetType);
+  NS_LOG_FUNCTION (this << packet << txVector.GetMode () << preamble << (uint32_t)aMpdu.packetType);
   NS_ASSERT (IsStateRx ());
   NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
   AmpduTag ampduTag;
@@ -753,7 +753,7 @@
 }
 
 void
-YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType)
+YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, uint32_t mpduReferenceNumber)
 {
   NS_LOG_FUNCTION (this << packet << txVector.GetMode () << preamble << (uint32_t)txVector.GetTxPowerLevel () << (uint32_t)packetType);
   /* Transmission can happen if:
@@ -788,10 +788,12 @@
     {
       dataRate500KbpsUnits = txVector.GetMode ().GetDataRate () * txVector.GetNss () / 500000;
     }
-  bool isShortPreamble = (WIFI_PREAMBLE_SHORT == preamble);
-  NotifyMonitorSniffTx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, isShortPreamble, txVector);
+  struct mpduInfo aMpdu;
+  aMpdu.packetType = packetType;
+  aMpdu.referenceNumber = mpduReferenceNumber;
+  NotifyMonitorSniffTx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, preamble, txVector, aMpdu);
   m_state->SwitchToTx (txDuration, packet, GetPowerDbm (txVector.GetTxPowerLevel ()), txVector, preamble);
-  m_channel->Send (this, packet, GetPowerDbm (txVector.GetTxPowerLevel ()) + m_txGainDb, txVector, preamble, packetType, txDuration);
+  m_channel->Send (this, packet, GetPowerDbm (txVector.GetTxPowerLevel ()) + m_txGainDb, txVector, preamble, aMpdu, txDuration);
 }
 
 uint32_t
@@ -1079,7 +1081,7 @@
 }
 
 void
-YansWifiPhy::EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, uint8_t packetType, Ptr<InterferenceHelper::Event> event)
+YansWifiPhy::EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, struct mpduInfo aMpdu, Ptr<InterferenceHelper::Event> event)
 {
   NS_LOG_FUNCTION (this << packet << event);
   NS_ASSERT (IsStateRx ());
@@ -1106,10 +1108,10 @@
             {
               dataRate500KbpsUnits = event->GetPayloadMode ().GetDataRate () * event->GetTxVector ().GetNss () / 500000;
             }
-          bool isShortPreamble = (WIFI_PREAMBLE_SHORT == event->GetPreambleType ());
-          double signalDbm = RatioToDb (event->GetRxPowerW ()) + 30;
-          double noiseDbm = RatioToDb (event->GetRxPowerW () / snrPer.snr) - GetRxNoiseFigure () + 30;
-          NotifyMonitorSniffRx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, isShortPreamble, event->GetTxVector (), signalDbm, noiseDbm);
+          struct snrDbm snr;
+          snr.signal = RatioToDb (event->GetRxPowerW ()) + 30;
+          snr.noise = RatioToDb (event->GetRxPowerW () / snrPer.snr) - GetRxNoiseFigure () + 30;
+          NotifyMonitorSniffRx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, event->GetPreambleType (), event->GetTxVector (), aMpdu, snr);
           m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetTxVector (), event->GetPreambleType ());
         }
       else
@@ -1125,7 +1127,7 @@
       m_state->SwitchFromRxEndError (packet, snrPer.snr);
     }
 
-  if (preamble == WIFI_PREAMBLE_NONE && packetType == 2)
+  if (preamble == WIFI_PREAMBLE_NONE && aMpdu.packetType == 2)
     {
       m_plcpSuccess = false;
     }
--- a/src/wifi/model/yans-wifi-phy.h	Wed Jul 08 00:09:46 2015 +0200
+++ b/src/wifi/model/yans-wifi-phy.h	Wed Jul 08 23:44:17 2015 +0200
@@ -105,14 +105,15 @@
    * \param rxPowerDbm the receive power in dBm
    * \param txVector the TXVECTOR of the arriving packet
    * \param preamble the preamble of the arriving packet
-   * \param packetType The type of the received packet (values: 0 not an A-MPDU, 1 corresponds to any packets in an A-MPDU except the last one, 2 is the last packet in an A-MPDU)
+   * \param aMpdu the type of the packet (0 is not A-MPDU, 1 is a MPDU that is part of an A-MPDU and 2 is the last MPDU in an A-MPDU)
+   *        and the A-MPDU reference number (must be a different value for each A-MPDU but the same for each subframe within one A-MPDU)
    * \param rxDuration the duration needed for the reception of the packet
    */
   void StartReceivePreambleAndHeader (Ptr<Packet> packet,
                                       double rxPowerDbm,
                                       WifiTxVector txVector,
                                       WifiPreamble preamble,
-                                      uint8_t packetType,
+                                      struct mpduInfo aMpdu,
                                       Time rxDuration);
   /**
    * Starting receiving the payload of a packet (i.e. the first bit of the packet has arrived).
@@ -120,13 +121,14 @@
    * \param packet the arriving packet
    * \param txVector the TXVECTOR of the arriving packet
    * \param preamble the preamble of the arriving packet
-   * \param packetType The type of the received packet (values: 0 not an A-MPDU, 1 corresponds to any packets in an A-MPDU except the last one, 2 is the last packet in an A-MPDU)
+   * \param aMpdu the type of the packet (0 is not A-MPDU, 1 is a MPDU that is part of an A-MPDU and 2 is the last MPDU in an A-MPDU)
+   *        and the A-MPDU reference number (must be a different value for each A-MPDU but the same for each subframe within one A-MPDU)
    * \param event the corresponding event of the first time the packet arrives
    */
   void StartReceivePacket (Ptr<Packet> packet,
                            WifiTxVector txVector,
                            WifiPreamble preamble,
-                           uint8_t packetType,
+                           struct mpduInfo aMpdu,
                            Ptr<InterferenceHelper::Event> event);
 
   /**
@@ -277,7 +279,7 @@
 
   virtual void SetReceiveOkCallback (WifiPhy::RxOkCallback callback);
   virtual void SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback);
-  virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txvector, enum WifiPreamble preamble, uint8_t packetType);
+  virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txvector, enum WifiPreamble preamble, uint8_t packetType, uint32_t mpduReferenceNumber);
   virtual void RegisterListener (WifiPhyListener *listener);
   virtual void UnregisterListener (WifiPhyListener *listener);
   virtual void SetSleepMode (void);
@@ -496,10 +498,11 @@
    *
    * \param packet the packet that the last bit has arrived
    * \param preamble the preamble of the arriving packet
-   * \param packetType The type of the received packet (values: 0 not an A-MPDU, 1 corresponds to any packets in an A-MPDU except the last one, 2 is the last packet in an A-MPDU)
+   * \param aMpdu the type of the packet (0 is not A-MPDU, 1 is a MPDU that is part of an A-MPDU and 2 is the last MPDU in an A-MPDU)
+   *        and the A-MPDU reference number (must be a different value for each A-MPDU but the same for each subframe within one A-MPDU)
    * \param event the corresponding event of the first time the packet arrives
    */
-  void EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, uint8_t packetType, Ptr<InterferenceHelper::Event> event);
+  void EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, struct mpduInfo aMpdu, Ptr<InterferenceHelper::Event> event);
 
   bool     m_initialized;         //!< Flag for runtime initialization
   double   m_edThresholdW;        //!< Energy detection threshold in watts