wifi: (fixes #2120) 802.11g backward compatible with 802.11b
authorSébastien Deronne <sebastien.deronne@gmail.com>
Wed, 17 Feb 2016 22:40:00 +0100
changeset 11881 8707c44ecc30
parent 11880 27a19e317de6
child 11882 303b328f07e9
wifi: (fixes #2120) 802.11g backward compatible with 802.11b
RELEASE_NOTES
examples/wireless/examples-to-run.py
examples/wireless/mixed-bg-network.cc
examples/wireless/wscript
src/wifi/doc/source/wifi-design.rst
src/wifi/model/aarf-wifi-manager.cc
src/wifi/model/aarfcd-wifi-manager.cc
src/wifi/model/amrr-wifi-manager.cc
src/wifi/model/ap-wifi-mac.cc
src/wifi/model/ap-wifi-mac.h
src/wifi/model/aparf-wifi-manager.cc
src/wifi/model/arf-wifi-manager.cc
src/wifi/model/capability-information.cc
src/wifi/model/capability-information.h
src/wifi/model/cara-wifi-manager.cc
src/wifi/model/erp-information.cc
src/wifi/model/erp-information.h
src/wifi/model/ideal-wifi-manager.cc
src/wifi/model/mac-low.cc
src/wifi/model/mgt-headers.cc
src/wifi/model/mgt-headers.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/regular-wifi-mac.cc
src/wifi/model/regular-wifi-mac.h
src/wifi/model/rraa-wifi-manager.cc
src/wifi/model/sta-wifi-mac.cc
src/wifi/model/wifi-mac.cc
src/wifi/model/wifi-mac.h
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/yans-wifi-phy.cc
src/wifi/model/yans-wifi-phy.h
src/wifi/wscript
--- a/RELEASE_NOTES	Wed Feb 17 11:22:02 2016 +0100
+++ b/RELEASE_NOTES	Wed Feb 17 22:40:00 2016 +0100
@@ -63,6 +63,7 @@
 - Bug 2041 - TCP RTO needs unit tests
 - Bug 2068 - Timestamp option conforms to RFC 7323
 - Bug 2116 - refactoring aggregation API
+- Bug 2120 - 802.11g networks are not compatible with 802.11b clients
 - Bug 2141 - TCP DataSent callback now correctly notifies sent data, without missing bytes in particular conditions
 - Bug 2150 - The TCP sender keeps retransmitting and does not terminate the connection after some retries.
 - Bug 2159 - TCP advertises wrong receive window
--- a/examples/wireless/examples-to-run.py	Wed Feb 17 11:22:02 2016 +0100
+++ b/examples/wireless/examples-to-run.py	Wed Feb 17 22:40:00 2016 +0100
@@ -30,6 +30,7 @@
     ("ofdm-ht-validation", "True", "True"),
     ("ofdm-validation", "True", "True"),
     ("ofdm-vht-validation", "True", "True"),
+    ("mixed-bg-network", "True", "True"),
 ]
 
 # A list of Python examples to run in order to ensure that they remain
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/wireless/mixed-bg-network.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -0,0 +1,306 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2016 Sébastien Deronne
+ *
+ * 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
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/ipv4-global-routing-helper.h"
+#include "ns3/internet-module.h"
+
+// This example shows how the presence of an 802.11b station in an 802.11g network does affect the performance.
+//
+// The example compares different scenarios depending on whether an 802.11b station is associated to the access point
+// and depending on the configuration of the following parameters:
+// - protection mode that is configured on the AP;
+// - whether short PLCP is supported by the 802.11b station;
+// - whether short slot time is supported by both the 802.11g station and the AP.
+//
+// The output results show that the presence of an 802.11b station strongly affects 802.11g performance.
+// Protection mechanisms ensure that the NAV value of 802.11b stations is set correctly in case of 802.11g transmissions.
+// In practice, those protection mechanism add a lot of overhead, resulting in reduced performance. CTS-To-Self introduces
+// less overhead than Rts-Cts, but is not heard by hidden stations (and is thus generally only recommended as a protection
+// mechanism for access points). Since short slot time is disabled once an 802.11b station enters the network, benefits from
+// short slot time are only observed in a pure-G configuration.
+//
+// The user can also select the payload size and can choose either an UDP or a TCP connection.
+// Example: ./waf --run "mixed-bg-network --isUdp=1"
+//
+// Network topology:
+//
+//   STA (802.11b)    AP (802.11b/g)   STA (802.11b/g)
+//   *                *                *
+//   |                |                |
+//   n1               n2               n3
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("ErpAndNonErp");
+
+class Experiment
+{
+public:
+  Experiment ();
+  double Run (bool enableProtection, bool enableShortSlotTime, bool enableShortPlcpPreamble, bool isMixed, bool isUdp, uint32_t payloadSize, uint32_t simulationTime);
+};
+
+Experiment::Experiment ()
+{
+}
+
+double
+Experiment::Run (bool enableProtection, bool enableShortSlotTime, bool enableShortPlcpPreamble, bool isMixed, bool isUdp, uint32_t payloadSize, uint32_t simulationTime)
+{
+  double throughput = 0;
+  uint32_t totalPacketsThrough = 0;
+  uint32_t nWifiB = 0;
+  if (isMixed)
+    {
+      nWifiB = 1;
+    }
+
+  NodeContainer wifiBStaNodes;
+  wifiBStaNodes.Create (nWifiB);
+  NodeContainer wifiGStaNodes;
+  wifiGStaNodes.Create (1);
+  NodeContainer wifiApNode;
+  wifiApNode.Create (1);
+
+  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
+  channel.AddPropagationLoss ("ns3::RangePropagationLossModel");
+
+  YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
+  phy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
+  phy.SetChannel (channel.Create ());
+
+  WifiHelper wifi;
+  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
+
+  // 802.11b STA
+  wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
+
+  WifiMacHelper mac;
+  Ssid ssid = Ssid ("ns-3-ssid");
+
+  mac.SetType ("ns3::StaWifiMac",
+               "Ssid", SsidValue (ssid),
+               "ActiveProbing", BooleanValue (false),
+               "ShortSlotTimeSupported", BooleanValue (enableShortSlotTime));
+    
+  // Configure the PLCP preamble type: long or short
+  phy.Set ("ShortPlcpPreambleSupported", BooleanValue (enableShortPlcpPreamble));
+
+  NetDeviceContainer bStaDevice;
+  bStaDevice = wifi.Install (phy, mac, wifiBStaNodes);
+  
+  // 802.11b/g STA
+  wifi.SetStandard (WIFI_PHY_STANDARD_80211g);
+  NetDeviceContainer gStaDevice;
+  gStaDevice = wifi.Install (phy, mac, wifiGStaNodes);
+  
+  // 802.11b/g AP
+  mac.SetType ("ns3::ApWifiMac",
+               "Ssid", SsidValue (ssid),
+               "BeaconGeneration", BooleanValue (true),
+               "EnableNonErpProtection", BooleanValue (enableProtection),
+               "ShortSlotTimeSupported", BooleanValue (enableShortSlotTime));
+    
+  NetDeviceContainer apDevice;
+  apDevice = wifi.Install (phy, mac, wifiApNode);
+
+  // Setting mobility model
+  MobilityHelper mobility;
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
+  if (isMixed)
+  {
+    positionAlloc->Add (Vector (5.0, 0.0, 0.0));
+  }
+  positionAlloc->Add (Vector (0.0, 5.0, 0.0));
+  
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (wifiApNode);
+  mobility.Install (wifiBStaNodes);
+  mobility.Install (wifiGStaNodes);
+
+  // Internet stack
+  InternetStackHelper stack;
+  stack.Install (wifiApNode);
+  stack.Install (wifiBStaNodes);
+  stack.Install (wifiGStaNodes);
+
+  Ipv4AddressHelper address;
+
+  address.SetBase ("192.168.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer bStaInterface;
+  bStaInterface = address.Assign (bStaDevice);
+  Ipv4InterfaceContainer gStaInterface;
+  gStaInterface = address.Assign (gStaDevice);
+  Ipv4InterfaceContainer ApInterface;
+  ApInterface = address.Assign (apDevice);
+
+  // Setting applications
+  if (isUdp)
+    {
+      UdpServerHelper myServer (9);
+      ApplicationContainer serverApp = myServer.Install (wifiApNode);
+      serverApp.Start (Seconds (0.0));
+      serverApp.Stop (Seconds (simulationTime + 1));
+
+      UdpClientHelper myClient (ApInterface.GetAddress (0), 9);
+      myClient.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
+      myClient.SetAttribute ("Interval", TimeValue (Time ("0.0002"))); //packets/s
+      myClient.SetAttribute ("PacketSize", UintegerValue (payloadSize));
+
+      ApplicationContainer clientApp = myClient.Install (wifiGStaNodes);
+      clientApp.Start (Seconds (1.0));
+      clientApp.Stop (Seconds (simulationTime + 1));
+  
+      Simulator::Stop (Seconds (simulationTime + 1));
+      Simulator::Run ();
+      Simulator::Destroy ();
+  
+      totalPacketsThrough = DynamicCast<UdpServer> (serverApp.Get (0))->GetReceived ();
+      throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0);
+    }
+  else
+    {
+      uint16_t port = 50000;
+      Address apLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
+      PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", apLocalAddress);
+      
+      ApplicationContainer sinkApp = packetSinkHelper.Install (wifiApNode.Get (0));
+      sinkApp.Start (Seconds (0.0));
+      sinkApp.Stop (Seconds (simulationTime + 1));
+
+      OnOffHelper onoff ("ns3::TcpSocketFactory",Ipv4Address::GetAny ());
+      onoff.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
+      onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
+      onoff.SetAttribute ("PacketSize", UintegerValue (payloadSize));
+      onoff.SetAttribute ("DataRate", DataRateValue (54000000)); //bit/s
+      
+      AddressValue remoteAddress (InetSocketAddress (ApInterface.GetAddress (0), port));
+      onoff.SetAttribute ("Remote", remoteAddress);
+      
+      ApplicationContainer apps;
+      apps.Add (onoff.Install (wifiGStaNodes));
+      apps.Start (Seconds (1.0));
+      apps.Stop (Seconds (simulationTime + 1));
+
+      Simulator::Stop (Seconds (simulationTime + 1));
+      Simulator::Run ();
+      Simulator::Destroy ();
+      
+      totalPacketsThrough = DynamicCast<PacketSink> (sinkApp.Get (0))->GetTotalRx ();
+      throughput += totalPacketsThrough * 8 / (simulationTime * 1000000.0);
+    }
+  
+  return throughput;
+}
+
+int main (int argc, char *argv[])
+{
+  uint32_t payloadSize = 1472; //bytes
+  uint32_t simulationTime = 10; //seconds
+  bool isUdp = true;
+  
+  CommandLine cmd;
+  cmd.AddValue ("payloadSize", "Payload size in bytes", payloadSize);
+  cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime);
+  cmd.AddValue ("isUdp", "UDP if set to 1, TCP otherwise", isUdp);
+  cmd.Parse (argc, argv);
+
+  Experiment experiment;
+  double throughput = 0;
+  std::cout << "Protection mode" << "\t\t" << "Slot time supported" << "\t\t" << "PLCP preamble supported" << "\t\t" << "Scenario" << "\t" << "Throughput" << std::endl;
+  
+  throughput = experiment.Run (false, false, false, false, isUdp, payloadSize, simulationTime);
+  if (throughput < 17 || throughput > 18)
+    {
+      NS_LOG_ERROR ("Obtained throughput is not in the expected boundaries!");
+      exit (1);
+    }
+  std::cout << "Disabled" << "\t\t" << "Long" << "\t\t\t\t" << "Long" << "\t\t\t\t" << "G-only" << "\t\t" << throughput <<" Mbit/s" << std::endl;
+  
+  throughput = experiment.Run (false, true, false, false, isUdp, payloadSize, simulationTime);
+  if (throughput < 29 || throughput > 30)
+    {
+      NS_LOG_ERROR ("Obtained throughput is not in the expected boundaries!");
+      exit (1);
+    }
+  std::cout << "Disabled" << "\t\t" << "Short" << "\t\t\t\t" << "Long" << "\t\t\t\t" << "G-only" << "\t\t" << throughput <<" Mbit/s" << std::endl;
+  
+  throughput = experiment.Run (false, false, false, true, isUdp, payloadSize, simulationTime);
+  if (throughput < 17 || throughput > 18)
+    {
+      NS_LOG_ERROR ("Obtained throughput is not in the expected boundaries!");
+      exit (1);
+    }
+  std::cout << "Disabled" << "\t\t" << "Long" << "\t\t\t\t" << "Long" << "\t\t\t\t" << "Mixed" << "\t\t" << throughput <<" Mbit/s" << std::endl;
+  
+  throughput = experiment.Run (false, false, true, true, isUdp, payloadSize, simulationTime);
+  if (throughput < 17 || throughput > 18)
+    {
+      NS_LOG_ERROR ("Obtained throughput is not in the expected boundaries!");
+      exit (1);
+    }
+  std::cout << "Disabled" << "\t\t" << "Long" << "\t\t\t\t" << "Short" << "\t\t\t\t" << "Mixed" << "\t\t" << throughput <<" Mbit/s" << std::endl;
+  
+  Config::SetDefault ("ns3::WifiRemoteStationManager::ProtectionMode", StringValue ("Rts-Cts"));
+  
+  throughput = experiment.Run (true, false, false, true, isUdp, payloadSize, simulationTime);
+  if (throughput < 9 || throughput > 10)
+    {
+      NS_LOG_ERROR ("Obtained throughput is not in the expected boundaries!");
+      exit (1);
+    }
+  std::cout << "RTS/CTS" << "\t\t\t" << "Long" << "\t\t\t\t" << "Long" << "\t\t\t\t" << "Mixed" << "\t\t" << throughput <<" Mbit/s" << std::endl;
+  
+  throughput = experiment.Run (true, false, true, true, isUdp, payloadSize, simulationTime);
+  if (throughput < 11 || throughput > 12)
+    {
+      NS_LOG_ERROR ("Obtained throughput is not in the expected boundaries!");
+      exit (1);
+    }
+  std::cout << "RTS/CTS" << "\t\t\t" << "Long" << "\t\t\t\t" << "Short" << "\t\t\t\t" << "Mixed" << "\t\t" << throughput <<" Mbit/s" << std::endl;
+  
+  Config::SetDefault ("ns3::WifiRemoteStationManager::ProtectionMode", StringValue ("Cts-To-Self"));
+  
+  throughput = experiment.Run (true, false, false, true, isUdp, payloadSize, simulationTime);
+  if (throughput < 12 || throughput > 13)
+    {
+      NS_LOG_ERROR ("Obtained throughput is not in the expected boundaries!");
+      exit (1);
+    }
+  std::cout << "CTS-TO-SELF" << "\t\t" << "Long" << "\t\t\t\t" << "Long" << "\t\t\t\t" << "Mixed" << "\t\t" << throughput <<" Mbit/s" << std::endl;
+  
+  throughput = experiment.Run (true, false, true, true, isUdp, payloadSize, simulationTime);
+  if (throughput < 14 || throughput > 15)
+    {
+      NS_LOG_ERROR ("Obtained throughput is not in the expected boundaries!");
+      exit (1);
+    }
+  std::cout << "CTS-TO-SELF" << "\t\t" << "Long" << "\t\t\t\t" << "Short" << "\t\t\t\t" << "Mixed" << "\t\t" << throughput <<" Mbit/s" << std::endl;
+  
+  return 0;
+}
--- a/examples/wireless/wscript	Wed Feb 17 11:22:02 2016 +0100
+++ b/examples/wireless/wscript	Wed Feb 17 22:40:00 2016 +0100
@@ -78,3 +78,6 @@
 
     obj = bld.create_ns3_program('simple-ht-hidden-stations', ['internet', 'mobility', 'wifi', 'applications'])    
     obj.source = 'simple-ht-hidden-stations.cc'
+
+    obj = bld.create_ns3_program('mixed-bg-network', ['internet', 'mobility', 'wifi', 'applications'])    
+    obj.source = 'mixed-bg-network.cc'
--- a/src/wifi/doc/source/wifi-design.rst	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/doc/source/wifi-design.rst	Wed Feb 17 22:40:00 2016 +0100
@@ -169,7 +169,6 @@
 this time.  Support for 802.11n and ac is evolving.  Some additional details
 are as follows:
 
-* 802.11g does not support 9 microseconds slot
 * 802.11e TXOP is not supported
 * BSSBasicRateSet for 802.11b has been assumed to be 1-2 Mbit/s
 * BSSBasicRateSet for 802.11a/g has been assumed to be 6-12-24 Mbit/s
--- a/src/wifi/model/aarf-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/aarf-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -254,7 +254,16 @@
       //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
       channelWidth = 20;
     }
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- a/src/wifi/model/aarfcd-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/aarfcd-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -326,7 +326,16 @@
       //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
       channelWidth = 20;
     }
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- a/src/wifi/model/amrr-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/amrr-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -356,8 +356,16 @@
       channelWidth = 20;
     }
   UpdateMode (station);
-  /// \todo can we implement something smarter ?
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- a/src/wifi/model/ap-wifi-mac.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/ap-wifi-mac.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -69,6 +69,11 @@
                    MakeBooleanAccessor (&ApWifiMac::SetBeaconGeneration,
                                         &ApWifiMac::GetBeaconGeneration),
                    MakeBooleanChecker ())
+    .AddAttribute ("EnableNonErpProtection", "Whether or not protection mechanism should be used when non-ERP STAs are present within the BSS."
+                   "This parameter is only used when ERP is supported by the AP.",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&ApWifiMac::m_enableNonErpProtection),
+                   MakeBooleanChecker ())
   ;
   return tid;
 }
@@ -93,6 +98,8 @@
 ApWifiMac::~ApWifiMac ()
 {
   NS_LOG_FUNCTION (this);
+  m_staList.clear();
+  m_nonErpStations.clear ();
 }
 
 void
@@ -190,6 +197,44 @@
   return 1;
 }
 
+bool
+ApWifiMac::GetShortSlotTimeEnabled (void) const
+{
+  if (m_nonErpStations.size () != 0)
+    {
+      return false;
+    }
+  if (m_erpSupported == true && GetShortSlotTimeSupported () == true)
+    {
+      for (std::list<Mac48Address>::const_iterator i = m_staList.begin (); i != m_staList.end (); i++)
+      {
+        if (m_stationManager->GetShortSlotTimeSupported (*i) == false)
+          {
+            return false;
+          }
+      }
+      return true;
+    }
+  return false;
+}
+
+bool
+ApWifiMac::GetShortPreambleEnabled (void) const
+{
+  if (m_erpSupported || m_phy->GetShortPlcpPreambleSupported ())
+    {
+      for (std::list<Mac48Address>::const_iterator i = m_nonErpStations.begin (); i != m_nonErpStations.end (); i++)
+      {
+        if (m_stationManager->GetShortPreambleSupported (*i) == false)
+          {
+            return false;
+          }
+      }
+      return true;
+    }
+  return false;
+}
+
 void
 ApWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from,
                         Mac48Address to)
@@ -338,10 +383,32 @@
 ApWifiMac::GetCapabilities (void) const
 {
   CapabilityInformation capabilities;
-  capabilities.SetShortPreamble (m_phy->GetShortPlcpPreamble ());
+  capabilities.SetShortPreamble (GetShortPreambleEnabled ());
+  capabilities.SetShortSlotTime (GetShortSlotTimeEnabled ());
   return capabilities;
 }
 
+ErpInformation
+ApWifiMac::GetErpInformation (void) const
+{
+  ErpInformation information;
+  information.SetErpSupported (1);
+  if (m_erpSupported)
+    {
+      information.SetNonErpPresent (!m_nonErpStations.empty ());
+      information.SetUseProtection (GetUseProtection ());
+      if (GetShortPreambleEnabled ())
+        {
+          information.SetBarkerPreambleMode (0);
+        }
+      else
+        {
+          information.SetBarkerPreambleMode (1);
+        }
+    }
+  return information;
+}
+
 HtCapabilities
 ApWifiMac::GetHtCapabilities (void) const
 {
@@ -428,6 +495,12 @@
   probe.SetSupportedRates (GetSupportedRates ());
   probe.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
   probe.SetCapabilities (GetCapabilities ());
+  m_stationManager->SetShortPreambleEnabled (GetShortPreambleEnabled ());
+  m_stationManager->SetShortSlotTimeEnabled (GetShortSlotTimeEnabled ());
+  if (m_erpSupported)
+    {
+      probe.SetErpInformation (GetErpInformation ());
+    }
   if (m_htSupported || m_vhtSupported)
     {
       probe.SetHtCapabilities (GetHtCapabilities ());
@@ -463,6 +536,7 @@
   if (success)
     {
       code.SetSuccess ();
+      m_staList.push_back (to);
     }
   else
     {
@@ -471,6 +545,10 @@
   assoc.SetSupportedRates (GetSupportedRates ());
   assoc.SetStatusCode (code);
   assoc.SetCapabilities (GetCapabilities ());
+  if (m_erpSupported)
+    {
+      assoc.SetErpInformation (GetErpInformation ());
+    }
   if (m_htSupported || m_vhtSupported)
     {
       assoc.SetHtCapabilities (GetHtCapabilities ());
@@ -506,6 +584,12 @@
   beacon.SetSupportedRates (GetSupportedRates ());
   beacon.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
   beacon.SetCapabilities (GetCapabilities ());
+  m_stationManager->SetShortPreambleEnabled (GetShortPreambleEnabled ());
+  m_stationManager->SetShortSlotTimeEnabled (GetShortSlotTimeEnabled ());
+  if (m_erpSupported)
+    {
+      beacon.SetErpInformation (GetErpInformation ());
+    }
   if (m_htSupported || m_vhtSupported)
     {
       beacon.SetHtCapabilities (GetHtCapabilities ());
@@ -520,6 +604,22 @@
   //The beacon has it's own special queue, so we load it in there
   m_beaconDca->Queue (packet, hdr);
   m_beaconEvent = Simulator::Schedule (m_beaconInterval, &ApWifiMac::SendOneBeacon, this);
+  
+  //If a STA that does not support Short Slot Time associates,
+  //the AP shall use long slot time beginning at the first Beacon
+  //subsequent to the association of the long slot time STA.
+  if (GetShortSlotTimeEnabled () == true)
+    {
+      //Enable short slot time and set cwMin to 15
+      SetSlot (MicroSeconds (9));
+      ConfigureContentionWindow (15, 1023);
+    }
+  else
+    {
+      //Disable short slot time and set CWmin to 31
+      SetSlot (MicroSeconds (20));
+      ConfigureContentionWindow (31, 1023);
+    }
 }
 
 void
@@ -646,15 +746,40 @@
               m_stationManager->AddSupportedPlcpPreamble (from, capabilities.IsShortPreamble ());
               SupportedRates rates = assocReq.GetSupportedRates ();
               bool problem = false;
+              bool isErpStation = false;
+              bool isDsssStation = false;
               for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
                 {
                   WifiMode mode = m_stationManager->GetBasicMode (i);
                   if (!rates.IsSupportedRate (mode.GetDataRate (m_phy->GetChannelWidth (), false, 1)))
                     {
-                      problem = true;
-                      break;
+                      if ((mode.GetModulationClass () == WIFI_MOD_CLASS_DSSS) || (mode.GetModulationClass () == WIFI_MOD_CLASS_HR_DSSS))
+                        {
+                          isDsssStation = false;
+                        }
+                      else if (mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM)
+                        {
+                          isErpStation = false;
+                        }
+                      if (isDsssStation == false && isErpStation == false)
+                        {
+                          problem = true;
+                          break;
+                        }
+                    }
+                  else
+                    {
+                      if ((mode.GetModulationClass () == WIFI_MOD_CLASS_DSSS) || (mode.GetModulationClass () == WIFI_MOD_CLASS_HR_DSSS))
+                        {
+                          isDsssStation = true;
+                        }
+                      else if (mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM)
+                        {
+                          isErpStation = true;
+                        }
                     }
                 }
+              m_stationManager->AddSupportedErpSlotTime (from, capabilities.IsShortSlotTime () && isErpStation);
               if (m_htSupported)
                 {
                   //check that the STA supports all MCSs in Basic MCS Set
@@ -730,6 +855,10 @@
                         }
                     }
                   m_stationManager->RecordWaitAssocTxOk (from);
+                  if (!isErpStation && isDsssStation)
+                    {
+                      m_nonErpStations.push_back (hdr->GetAddr2 ());
+                    }
                   // send assoc response with success status.
                   SendAssocResp (hdr->GetAddr2 (), true);
                 }
@@ -738,6 +867,22 @@
           else if (hdr->IsDisassociation ())
             {
               m_stationManager->RecordDisassociated (from);
+              for (std::list<Mac48Address>::iterator i = m_staList.begin (); i != m_staList.end (); i++)
+              {
+                if ((*i) == from)
+                  {
+                    m_staList.erase (i);
+                    break;
+                  }
+              }
+              for (std::list<Mac48Address>::iterator j = m_nonErpStations.begin (); j != m_nonErpStations.end (); j++)
+              {
+                if ((*j) == from)
+                  {
+                    m_nonErpStations.erase (j);
+                    break;
+                  }
+              }
               return;
             }
         }
@@ -798,4 +943,13 @@
   RegularWifiMac::DoInitialize ();
 }
 
+bool
+ApWifiMac::GetUseProtection (void) const
+{
+  bool useProtection = !m_nonErpStations.empty () && m_enableNonErpProtection;
+  m_stationManager->SetUseProtection (useProtection);
+  return useProtection;
+}
+
+
 } //namespace ns3
--- a/src/wifi/model/ap-wifi-mac.h	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/ap-wifi-mac.h	Wed Feb 17 22:40:00 2016 +0100
@@ -29,6 +29,7 @@
 #include "vht-capabilities.h"
 #include "amsdu-subframe-header.h"
 #include "supported-rates.h"
+#include "erp-information.h"
 #include "ns3/random-variable-stream.h"
 
 namespace ns3 {
@@ -99,6 +100,19 @@
    * Start beacon transmission immediately.
    */
   void StartBeaconing (void);
+  /**
+   * Determine whether short slot time should be enabled or not in the BSS.
+   * Typically, true is returned only when there is no non-erp stations associated
+   * to the AP, and that short slot time is supported by the AP and by all other
+   * ERP stations that are associated to the AP. Otherwise, false is returned.
+   */
+  bool GetShortSlotTimeEnabled (void) const;
+  /**
+   * Determine whether short preamble should be enabled or not in the BSS.
+   * Typically, true is returned only when the AP and all associated 
+   * stations support short PLCP preamble.
+   */
+  bool GetShortPreambleEnabled (void) const;
 
   /**
    * Assign a fixed random variable stream number to the random variables
@@ -188,6 +202,12 @@
    */
   CapabilityInformation GetCapabilities (void) const;
   /**
+   * Return the ERP information of the current AP.
+   *
+   * \return the ERP information that we support
+   */
+  ErpInformation GetErpInformation (void) const;
+  /**
    * Return the HT capability of the current AP.
    *
    * \return the HT capability that we support
@@ -218,16 +238,21 @@
    * \return true if beacons are periodically generated, false otherwise
    */
   bool GetBeaconGeneration (void) const;
+  
+  bool GetUseProtection (void) const;
 
   virtual void DoDispose (void);
   virtual void DoInitialize (void);
 
   Ptr<DcaTxop> m_beaconDca;                  //!< Dedicated DcaTxop for beacons
   Time m_beaconInterval;                     //!< Interval between beacons
-  bool m_enableBeaconGeneration;             //!< Flag if beacons are being generated
+  bool m_enableBeaconGeneration;             //!< Flag whether beacons are being generated
   EventId m_beaconEvent;                     //!< Event to generate one beacon
   Ptr<UniformRandomVariable> m_beaconJitter; //!< UniformRandomVariable used to randomize the time of the first beacon
-  bool m_enableBeaconJitter;                 //!< Flag if the first beacon should be generated at random time
+  bool m_enableBeaconJitter;                 //!< Flag whether the first beacon should be generated at random time
+  std::list<Mac48Address> m_staList;         //!< List of all stations currently associated to the AP
+  std::list<Mac48Address> m_nonErpStations;  //!< List of all 802.11b stations currently associated to the AP
+  bool m_enableNonErpProtection;             //!< Flag whether protection mechanism is used or not when non-ERP STAs are present within the BSS
 };
 
 } //namespace ns3
--- a/src/wifi/model/aparf-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/aparf-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -345,7 +345,16 @@
       //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
       channelWidth = 20;
     }
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- a/src/wifi/model/arf-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/arf-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -230,7 +230,16 @@
       //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
       channelWidth = 20;
     }
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- a/src/wifi/model/capability-information.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/capability-information.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -57,6 +57,16 @@
     }
 }
 
+void
+CapabilityInformation::SetShortSlotTime (bool shortSlotTime)
+{
+  NS_LOG_FUNCTION (this);
+  if (shortSlotTime)
+    {
+      Set (10);
+    }
+}
+
 bool
 CapabilityInformation::IsEss (void) const
 {
@@ -78,6 +88,13 @@
   return Is (5);
 }
 
+bool
+CapabilityInformation::IsShortSlotTime (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return Is (10);
+}
+
 void
 CapabilityInformation::Set (uint8_t n)
 {
--- a/src/wifi/model/capability-information.h	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/capability-information.h	Wed Feb 17 22:40:00 2016 +0100
@@ -50,10 +50,18 @@
    * Set the short preamble bit
    * in the capability information field.
    *
-   * shortPreamble the short preamble bit
+   * /param shortPreamble the short preamble bit
    *
    */
   void SetShortPreamble (bool shortPreamble);
+  /**
+   * Set the short slot time bit
+   * in the capability information field.
+   *
+   * /param shortslotTime the short preamble bit
+   *
+   */
+  void SetShortSlotTime (bool shortSlotTime);
 
   /**
    * Check if the Extended Service Set (ESS) bit
@@ -79,6 +87,14 @@
    *         field is set to 1
    */
   bool IsShortPreamble (void) const;
+  /**
+   * Check if the short slot time
+   * in the capability information field is set to 1.
+   *
+   * \return short slot time bit in the capability information
+   *         field is set to 1
+   */
+  bool IsShortSlotTime (void) const;
 
   /**
    * Return the serialized size of capability
--- a/src/wifi/model/cara-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/cara-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -205,7 +205,16 @@
       //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
       channelWidth = 20;
     }
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/erp-information.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -0,0 +1,151 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 Sébastien Deronne
+ *
+ * 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
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
+ */
+
+#include "erp-information.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("ErpInformation");
+
+ErpInformation::ErpInformation ()
+  : m_erpInformation (0),
+    m_erpSupported (0)
+{
+}
+
+WifiInformationElementId
+ErpInformation::ElementId () const
+{
+  return IE_ERP_INFORMATION;
+}
+
+void
+ErpInformation::SetErpSupported (uint8_t erpSupported)
+{
+  m_erpSupported = erpSupported;
+}
+
+void
+ErpInformation::SetBarkerPreambleMode (uint8_t barkerPreambleMode)
+{
+  m_erpInformation |= (barkerPreambleMode & 0x01) << 2;
+}
+
+void
+ErpInformation::SetUseProtection (uint8_t useProtection)
+{
+  m_erpInformation |= (useProtection & 0x01) << 1;
+}
+
+void
+ErpInformation::SetNonErpPresent (uint8_t nonErpPresent)
+{
+  m_erpInformation |= nonErpPresent & 0x01;
+}
+
+uint8_t
+ErpInformation::GetBarkerPreambleMode (void) const
+{
+  return ((m_erpInformation >> 2) & 0x01);
+}
+
+uint8_t
+ErpInformation::GetUseProtection (void) const
+{
+  return ((m_erpInformation >> 1) & 0x01);
+}
+
+uint8_t
+ErpInformation::GetNonErpPresent (void) const
+{
+  return (m_erpInformation & 0x01);
+}
+
+uint8_t
+ErpInformation::GetInformationFieldSize () const
+{
+  NS_ASSERT (m_erpSupported > 0);
+  return 1;
+}
+
+Buffer::Iterator
+ErpInformation::Serialize (Buffer::Iterator i) const
+{
+  if (m_erpSupported < 1)
+    {
+      return i;
+    }
+  return WifiInformationElement::Serialize (i);
+}
+
+uint16_t
+ErpInformation::GetSerializedSize () const
+{
+  if (m_erpSupported < 1)
+    {
+      return 0;
+    }
+  return WifiInformationElement::GetSerializedSize ();
+}
+
+void
+ErpInformation::SerializeInformationField (Buffer::Iterator start) const
+{
+  if (m_erpSupported == 1)
+    {
+      start.WriteU8 (m_erpInformation);
+    }
+}
+
+uint8_t
+ErpInformation::DeserializeInformationField (Buffer::Iterator start,
+                                             uint8_t length)
+{
+  Buffer::Iterator i = start;
+  m_erpInformation = i.ReadU8 ();
+  return length;
+}
+
+ATTRIBUTE_HELPER_CPP (ErpInformation);
+
+std::ostream &
+operator << (std::ostream &os, const ErpInformation &erpinformation)
+{
+  os <<  bool (erpinformation.GetBarkerPreambleMode ())
+     << "|" << bool (erpinformation.GetUseProtection ())
+     << "|" << bool (erpinformation.GetNonErpPresent ());
+
+  return os;
+}
+
+std::istream &operator >> (std::istream &is, ErpInformation &erpinformation)
+{
+  bool c1, c2, c3;
+  is >> c1 >> c2 >> c3;
+  erpinformation.SetBarkerPreambleMode (c1);
+  erpinformation.SetUseProtection (c2);
+  erpinformation.SetNonErpPresent (c3);
+
+  return is;
+}
+
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/erp-information.h	Wed Feb 17 22:40:00 2016 +0100
@@ -0,0 +1,119 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 Sébastien Deronne
+ *
+ * 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
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
+ */
+
+#ifndef ERP_INFORMATION_H
+#define ERP_INFORMATION_H
+
+#include <stdint.h>
+#include <ostream>
+#include "ns3/buffer.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+
+/**
+ * \brief The ErpInformation Information Element
+ * \ingroup wifi
+ *
+ * This class knows how to serialise and deserialise the ErpInformation Information Element.
+ */
+class ErpInformation : public WifiInformationElement
+{
+public:
+  ErpInformation ();
+  void SetErpSupported (uint8_t erpSupported);
+  
+  /**
+   * Set the Barker_Preamble_Mode field in the ErpInformation information element.
+   *
+   * \param barkerPreambleMode the Barker_Preamble_Mode field in the ErpInformation information element
+   */
+  void SetBarkerPreambleMode (uint8_t barkerPreambleMode);
+  /**
+   * Set the Use_Protection field in the ErpInformation information element.
+   *
+   * \param useProtection the Use_Protection field in the ErpInformation information element
+   */
+  void SetUseProtection (uint8_t useProtection);
+  /**
+   * Set the Non_Erp_Present field in the ErpInformation information element.
+   *
+   * \param nonErpPresent the Non_Erp_Present field in the ErpInformation information element
+   */
+  void SetNonErpPresent (uint8_t nonErpPresent);
+
+  /*
+   * Return the Barker_Preamble_Mode field in the ErpInformation information element.
+   *
+   * \return the Barker_Preamble_Mode field in the ErpInformation information element
+   */
+  uint8_t GetBarkerPreambleMode (void) const;
+  /*
+   * Return the Use_Protection field in the ErpInformation information element.
+   *
+   * \return the Use_Protection field in the ErpInformation information element
+   */
+  uint8_t GetUseProtection (void) const;
+  /*
+   * Return the Non_Erp_Present field in the ErpInformation information element.
+   *
+   * \return the Non_Erp_Present field in the ErpInformation information element
+   */
+  uint8_t GetNonErpPresent (void) const;
+
+  WifiInformationElementId ElementId () const;
+  uint8_t GetInformationFieldSize () const;
+  void SerializeInformationField (Buffer::Iterator start) const;
+  uint8_t DeserializeInformationField (Buffer::Iterator start,
+                                       uint8_t length);
+    
+  /**
+   * This information element is a bit special in that it is only
+   * included if the STA is an ERP STA. To support this we
+   * override the Serialize and GetSerializedSize methods of
+   * WifiInformationElement.
+   *
+   * \param start
+   *
+   * \return an iterator
+   */
+  Buffer::Iterator Serialize (Buffer::Iterator start) const;
+  /**
+   * Return the serialized size of this ErpInformation information element.
+   *
+   * \return the serialized size of this ErpInformation information element
+   */
+  uint16_t GetSerializedSize () const;
+
+private:
+  uint8_t m_erpInformation;
+
+  //This is used to decide whether this element should be added to the frame or not
+  bool m_erpSupported;
+};
+
+std::ostream &operator << (std::ostream &os, const ErpInformation &erpinformation);
+std::istream &operator >> (std::istream &is, ErpInformation &erpinformation);
+
+ATTRIBUTE_HELPER_HEADER (ErpInformation);
+
+} //namespace ns3
+
+#endif /* ERP_INFORMATION_H */
--- a/src/wifi/model/ideal-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/ideal-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -187,15 +187,32 @@
   //ensure correct packet delivery.
   double maxThreshold = 0.0;
   WifiMode maxMode = GetDefaultMode ();
-  for (uint32_t i = 0; i < GetNBasicModes (); i++)
+  if (GetUseProtection () == false)
     {
-      WifiMode mode = GetBasicMode (i);
-      double threshold = GetSnrThreshold (mode);
-      if (threshold > maxThreshold
-          && threshold < station->m_lastSnr)
+      for (uint32_t i = 0; i < GetNBasicModes (); i++)
         {
-          maxThreshold = threshold;
-          maxMode = mode;
+          WifiMode mode = GetBasicMode (i);
+          double threshold = GetSnrThreshold (mode);
+          if (threshold > maxThreshold
+              && threshold < station->m_lastSnr)
+            {
+              maxThreshold = threshold;
+              maxMode = mode;
+            }
+        }
+    }
+  else
+    {
+      for (uint32_t i = 0; i < GetNNonErpBasicModes (); i++)
+        {
+          WifiMode mode = GetNonErpBasicMode (i);
+          double threshold = GetSnrThreshold (mode);
+          if (threshold > maxThreshold
+              && threshold < station->m_lastSnr)
+            {
+              maxThreshold = threshold;
+              maxMode = mode;
+            }
         }
     }
   uint32_t channelWidth = GetChannelWidth (station);
--- a/src/wifi/model/mac-low.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/mac-low.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -807,7 +807,7 @@
     }
   else
     {
-      if (m_ctsToSelfSupported && NeedCtsToSelf ())
+      if ((m_ctsToSelfSupported || m_stationManager->GetUseProtection ()) && NeedCtsToSelf ())
         {
           SendCtsToSelf ();
         }
@@ -824,9 +824,9 @@
 bool
 MacLow::NeedRts (void)
 {
-  return m_stationManager->NeedRts (m_currentHdr.GetAddr1 (),
-                                    &m_currentHdr,
-                                    m_currentPacket);
+  WifiTxVector dataTxVector = GetDataTxVector (m_currentPacket, &m_currentHdr);
+  return m_stationManager->NeedRts (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                    m_currentPacket, dataTxVector);
 }
 
 bool
@@ -1271,7 +1271,16 @@
 MacLow::GetAckDuration (WifiTxVector ackTxVector) const
 {
   NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
-  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, WIFI_PREAMBLE_LONG, m_phy->GetFrequency ());
+  WifiPreamble preamble;
+  if (m_stationManager->GetShortPreambleEnabled ())
+    {
+      preamble = WIFI_PREAMBLE_SHORT;
+    }
+  else
+    {
+      preamble = WIFI_PREAMBLE_LONG;
+    }
+  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble, m_phy->GetFrequency ());
 }
 
 Time
@@ -1286,6 +1295,10 @@
     {
       preamble = WIFI_PREAMBLE_HT_MF;
     }
+  else if (m_stationManager->GetShortPreambleEnabled ())
+    {
+      preamble = WIFI_PREAMBLE_SHORT;
+    }
   else
     {
       preamble = WIFI_PREAMBLE_LONG;
@@ -1304,7 +1317,16 @@
 MacLow::GetCtsDuration (WifiTxVector ctsTxVector) const
 {
   NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
-  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, WIFI_PREAMBLE_LONG, m_phy->GetFrequency ());
+  WifiPreamble preamble;
+  if (m_stationManager->GetShortPreambleEnabled ())
+    {
+      preamble = WIFI_PREAMBLE_SHORT;
+    }
+  else
+    {
+      preamble = WIFI_PREAMBLE_LONG;
+    }
+  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency ());
 }
 
 uint32_t
@@ -1399,9 +1421,13 @@
         {
           preamble = WIFI_PREAMBLE_HT_GF;
         }
+      //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
+      else if (m_stationManager->GetShortPreambleEnabled ())
+        {
+          preamble = WIFI_PREAMBLE_SHORT;
+        }
       else
         {
-          //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
           preamble = WIFI_PREAMBLE_LONG;
         }
       txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency ());
@@ -1421,7 +1447,7 @@
     {
       preamble = WIFI_PREAMBLE_HT_MF;
     }
-  else if (m_phy->GetShortPlcpPreamble () && m_stationManager->GetShortPreambleSupported (m_currentHdr.GetAddr1 ()))
+  else if (m_stationManager->GetShortPreambleEnabled ())
     {
       preamble = WIFI_PREAMBLE_SHORT;
     }
@@ -1461,7 +1487,7 @@
         {
           preamble = WIFI_PREAMBLE_HT_MF;
         }
-      else if (m_phy->GetShortPlcpPreamble () && m_stationManager->GetShortPreambleSupported (m_currentHdr.GetAddr1 ()))
+      else if (m_stationManager->GetShortPreambleEnabled ())
         {
           preamble = WIFI_PREAMBLE_SHORT;
         }
@@ -1803,7 +1829,12 @@
     {
       preamble = WIFI_PREAMBLE_HT_GF;
     }
-  else //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
+  //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
+  else if (m_stationManager->GetShortPreambleEnabled ())
+    {
+      preamble = WIFI_PREAMBLE_SHORT;
+    }
+  else
     {
       preamble = WIFI_PREAMBLE_LONG;
     }
@@ -1881,7 +1912,7 @@
     {
       preamble = WIFI_PREAMBLE_HT_MF;
     }
-  else if (m_phy->GetShortPlcpPreamble () && m_stationManager->GetShortPreambleSupported (m_currentHdr.GetAddr1 ()))
+  else if (m_stationManager->GetShortPreambleEnabled ())
     {
       preamble = WIFI_PREAMBLE_SHORT;
     }
@@ -1969,7 +2000,7 @@
     {
       preamble = WIFI_PREAMBLE_HT_MF;
     }
-  else if (m_phy->GetShortPlcpPreamble () && m_stationManager->GetShortPreambleSupported (m_currentHdr.GetAddr1 ()))
+  else if (m_stationManager->GetShortPreambleEnabled ())
     {
       preamble = WIFI_PREAMBLE_SHORT;
     }
@@ -2053,13 +2084,17 @@
   cts.SetNoRetry ();
   cts.SetAddr1 (m_self);
 
-  WifiTxVector ctsTxVector = GetCtsToSelfTxVector (m_currentPacket, &m_currentHdr);
+  WifiTxVector ctsTxVector = GetRtsTxVector (m_currentPacket, &m_currentHdr);
 
   WifiPreamble preamble;
   if (ctsTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
     {
       preamble = WIFI_PREAMBLE_HT_MF;
     }
+  else if (m_stationManager->GetShortPreambleEnabled ())
+    {
+      preamble = WIFI_PREAMBLE_SHORT;
+    }
   else
     {
       preamble = WIFI_PREAMBLE_LONG;
@@ -2162,8 +2197,19 @@
   SnrTag tag;
   tag.Set (rtsSnr);
   packet->AddPacketTag (tag);
+  
+  WifiPreamble preamble;
+  if (m_stationManager->GetShortPreambleEnabled ())
+    {
+      preamble = WIFI_PREAMBLE_SHORT;
+    }
+  else
+    {
+      preamble = WIFI_PREAMBLE_LONG;
+    }
 
-  ForwardDown (packet, &cts, ctsTxVector, WIFI_PREAMBLE_LONG);
+  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
+  ForwardDown (packet, &cts, ctsTxVector, preamble);
 }
 
 void
@@ -2203,7 +2249,7 @@
     {
       preamble = WIFI_PREAMBLE_HT_MF;
     }
-  else if (m_phy->GetShortPlcpPreamble () && m_stationManager->GetShortPreambleSupported (m_currentHdr.GetAddr1 ()))
+  else if (m_stationManager->GetShortPreambleEnabled ())
     {
       preamble = WIFI_PREAMBLE_SHORT;
     }
@@ -2319,9 +2365,19 @@
   SnrTag tag;
   tag.Set (dataSnr);
   packet->AddPacketTag (tag);
+  
+  WifiPreamble preamble;
+  if (m_stationManager->GetShortPreambleEnabled ())
+    {
+      preamble = WIFI_PREAMBLE_SHORT;
+    }
+  else
+    {
+      preamble = WIFI_PREAMBLE_LONG;
+    }
 
   //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
-  ForwardDown (packet, &ack, ackTxVector, WIFI_PREAMBLE_LONG);
+  ForwardDown (packet, &ack, ackTxVector, preamble);
 }
 
 bool
@@ -2616,10 +2672,15 @@
     {
       preamble = WIFI_PREAMBLE_HT_MF;
     }
+  else if (m_stationManager->GetShortPreambleEnabled ())
+    {
+      preamble = WIFI_PREAMBLE_SHORT;
+    }
   else
     {
       preamble = WIFI_PREAMBLE_LONG;
     }
+
   ForwardDown (packet, &hdr, blockAckReqTxVector, preamble);
   m_currentPacket = 0;
 }
@@ -2838,7 +2899,7 @@
     {
       preamble = WIFI_PREAMBLE_HT_MF;
     }
-  else if (m_phy->GetShortPlcpPreamble () && m_stationManager->GetShortPreambleSupported (m_currentHdr.GetAddr1 ()))
+  else if (m_stationManager->GetShortPreambleEnabled ())
     {
       preamble = WIFI_PREAMBLE_SHORT;
     }
--- a/src/wifi/model/mgt-headers.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/mgt-headers.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -239,6 +239,18 @@
   m_rates = rates;
 }
 
+void
+MgtProbeResponseHeader::SetErpInformation (ErpInformation erpInformation)
+{
+  m_erpInformation = erpInformation;
+}
+
+ErpInformation
+MgtProbeResponseHeader::GetErpInformation (void) const
+{
+  return m_erpInformation;
+}
+
 TypeId
 MgtProbeResponseHeader::GetTypeId (void)
 {
@@ -266,6 +278,7 @@
   size += m_ssid.GetSerializedSize ();
   size += m_rates.GetSerializedSize ();
   //size += 3; //ds parameter set
+  size += m_erpInformation.GetSerializedSize ();
   size += m_rates.extended.GetSerializedSize ();
   size += m_htCapability.GetSerializedSize ();
   size += m_vhtCapability.GetSerializedSize ();
@@ -277,6 +290,7 @@
 {
   os << "ssid=" << m_ssid << ", "
      << "rates=" << m_rates << ", "
+     << "ERP information=" << m_erpInformation << ", "
      << "HT Capabilities=" << m_htCapability << " , "
      << "VHT Capabilities= " << m_vhtCapability;
 }
@@ -300,6 +314,7 @@
   i = m_ssid.Serialize (i);
   i = m_rates.Serialize (i);
   //i.WriteU8 (0, 3); //ds parameter set.
+  i = m_erpInformation.Serialize (i);
   i = m_rates.extended.Serialize (i);
   i = m_htCapability.Serialize (i);
   i = m_vhtCapability.Serialize (i);
@@ -316,6 +331,7 @@
   i = m_ssid.Deserialize (i);
   i = m_rates.Deserialize (i);
   //i.Next (3); //ds parameter set
+  i = m_erpInformation.DeserializeIfPresent (i);
   i = m_rates.extended.DeserializeIfPresent (i);
   i = m_htCapability.DeserializeIfPresent (i);
   i = m_vhtCapability.DeserializeIfPresent (i);
@@ -454,9 +470,9 @@
   size += 2;
   size += m_ssid.GetSerializedSize ();
   size += m_rates.GetSerializedSize ();
+  size += m_rates.extended.GetSerializedSize ();
   size += m_htCapability.GetSerializedSize ();
   size += m_vhtCapability.GetSerializedSize ();
-  size += m_rates.extended.GetSerializedSize ();
   return size;
 }
 
@@ -572,6 +588,19 @@
   return m_htCapability;
 }
 
+void
+MgtAssocResponseHeader::SetErpInformation (ErpInformation erpInformation)
+{
+  m_erpInformation = erpInformation;
+}
+
+ErpInformation
+MgtAssocResponseHeader::GetErpInformation (void) const
+{
+  return m_erpInformation;
+}
+
+
 TypeId
 MgtAssocResponseHeader::GetTypeId (void)
 {
@@ -597,6 +626,7 @@
   size += m_code.GetSerializedSize ();
   size += 2; //aid
   size += m_rates.GetSerializedSize ();
+  size += m_erpInformation.GetSerializedSize ();
   size += m_rates.extended.GetSerializedSize ();
   size += m_htCapability.GetSerializedSize ();
   size += m_vhtCapability.GetSerializedSize ();
@@ -608,6 +638,7 @@
 {
   os << "status code=" << m_code << ", "
      << "rates=" << m_rates << ", "
+     << "ERP information=" << m_erpInformation << ", "
      << "HT Capabilities=" << m_htCapability << " , "
      << "VHT Capabilities= " << m_vhtCapability;
 }
@@ -620,6 +651,7 @@
   i = m_code.Serialize (i);
   i.WriteHtolsbU16 (m_aid);
   i = m_rates.Serialize (i);
+  i = m_erpInformation.Serialize (i);
   i = m_rates.extended.Serialize (i);
   i = m_htCapability.Serialize (i);
   i = m_vhtCapability.Serialize (i);
@@ -633,6 +665,7 @@
   i = m_code.Deserialize (i);
   m_aid = i.ReadLsbtohU16 ();
   i = m_rates.Deserialize (i);
+  i = m_erpInformation.DeserializeIfPresent (i);
   i = m_rates.extended.DeserializeIfPresent (i);
   i = m_htCapability.DeserializeIfPresent (i);
   i = m_vhtCapability.DeserializeIfPresent (i);
--- a/src/wifi/model/mgt-headers.h	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/mgt-headers.h	Wed Feb 17 22:40:00 2016 +0100
@@ -32,6 +32,7 @@
 #include "ssid.h"
 #include "ht-capabilities.h"
 #include "vht-capabilities.h"
+#include "erp-information.h"
 
 namespace ns3 {
 
@@ -181,16 +182,22 @@
    */
   HtCapabilities GetHtCapabilities (void) const;
   /**
-    * Set the VHT capabilities.
-    *
-    * \param vhtcapabilities VHT capabilities
-    */
+   * Return the ERP information.
+   *
+   * \return the ERP information
+   */
+  ErpInformation GetErpInformation (void) const;
+  /**
+   * Set the VHT capabilities.
+   *
+   * \param vhtcapabilities VHT capabilities
+   */
   void SetVhtCapabilities (VhtCapabilities vhtcapabilities);
   /**
-  * Return the VHT capabilities.
-  *
-  * \return VHT capabilities
-  */
+   * Return the VHT capabilities.
+   *
+   * \return VHT capabilities
+   */
   VhtCapabilities GetVhtCapabilities (void) const;
   /**
    * Set the HT capabilities.
@@ -210,6 +217,12 @@
    * \param code the status code
    */
   void SetStatusCode (StatusCode code);
+  /**
+   * Set the ERP information.
+   *
+   * \param erpInformation the ERP information
+   */
+  void SetErpInformation (ErpInformation erpInformation);
 
   /**
    * Register this type.
@@ -222,6 +235,7 @@
   virtual void Serialize (Buffer::Iterator start) const;
   virtual uint32_t Deserialize (Buffer::Iterator start);
 
+
 private:
   SupportedRates m_rates; //!< List of supported rates
   CapabilityInformation m_capability; //!< Capability information
@@ -229,6 +243,7 @@
   uint16_t m_aid;
   HtCapabilities m_htCapability; //!< HT capabilities
   VhtCapabilities m_vhtCapability; //!< VHT capabilities
+  ErpInformation m_erpInformation;    //!< ERP information
 };
 
 
@@ -266,6 +281,12 @@
    */
   SupportedRates GetSupportedRates (void) const;
   /**
+   * Set the HT capabilities.
+   *
+   * \param htcapabilities HT capabilities
+   */
+  void SetHtCapabilities (HtCapabilities htcapabilities);
+  /**
    * Return the HT capabilities.
    *
    * \return HT capabilities
@@ -285,13 +306,6 @@
   VhtCapabilities GetVhtCapabilities (void) const;
 
   /**
-   * Set the HT capabilities.
-   *
-   * \param htcapabilities HT capabilities
-   */
-  void SetHtCapabilities (HtCapabilities htcapabilities);
-
-  /**
    * Register this type.
    * \return The TypeId.
    */
@@ -304,9 +318,9 @@
 
 
 private:
-  Ssid m_ssid;                   //!< Service Set ID (SSID)
-  SupportedRates m_rates;        //!< List of supported rates
-  HtCapabilities m_htCapability; //!< HT capabilities
+  Ssid m_ssid;                     //!< Service Set ID (SSID)
+  SupportedRates m_rates;          //!< List of supported rates
+  HtCapabilities m_htCapability;   //!< HT capabilities
   VhtCapabilities m_vhtCapability; //!< VHT capabilities
 };
 
@@ -352,12 +366,18 @@
    */
   HtCapabilities GetHtCapabilities (void) const;
   /**
-  * Return the VHT capabilities.
-  *
-  * \return VHT capabilities
-  */
+   * Return the VHT capabilities.
+   *
+   * \return VHT capabilities
+   */
   VhtCapabilities GetVhtCapabilities (void) const;
   /**
+   * Return the ERP information.
+   *
+   * \return the ERP information
+   */
+  ErpInformation GetErpInformation (void) const;
+  /**
    * Set the Capability information.
    *
    * \param capabilities Capability information
@@ -394,6 +414,12 @@
    */
   void SetSupportedRates (SupportedRates rates);
   /**
+   * Set the ERP information.
+   *
+   * \param erpInformation the ERP information
+   */
+  void SetErpInformation (ErpInformation erpInformation);
+  /**
    * Return the time stamp.
    *
    * \return time stamp
@@ -411,6 +437,7 @@
   virtual void Serialize (Buffer::Iterator start) const;
   virtual uint32_t Deserialize (Buffer::Iterator start);
 
+
 private:
   uint64_t m_timestamp;               //!< Timestamp
   Ssid m_ssid;                        //!< Service set ID (SSID)
@@ -419,6 +446,7 @@
   CapabilityInformation m_capability; //!< Capability information
   HtCapabilities m_htCapability;      //!< HT capabilities
   VhtCapabilities m_vhtCapability;    //!< VHT capabilities
+  ErpInformation m_erpInformation;    //!< ERP information
 };
 
 
--- a/src/wifi/model/minstrel-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/minstrel-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -502,7 +502,16 @@
       //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
       channelWidth = 20;
     }
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- a/src/wifi/model/onoe-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/onoe-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -298,8 +298,16 @@
       channelWidth = 20;
     }
   UpdateMode (station);
-  /// \todo can we implement something smarter ?
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- a/src/wifi/model/parf-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/parf-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -317,7 +317,16 @@
       //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
       channelWidth = 20;
     }
-  return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (station, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (station), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- a/src/wifi/model/regular-wifi-mac.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/regular-wifi-mac.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -41,7 +41,8 @@
 
 RegularWifiMac::RegularWifiMac () :
   m_htSupported (0),
-  m_vhtSupported (0)
+  m_vhtSupported (0),
+  m_erpSupported (0)
 {
   NS_LOG_FUNCTION (this);
   m_rxMiddle = new MacRxMiddle ();
@@ -429,6 +430,19 @@
   return m_htSupported;
 }
 
+bool
+RegularWifiMac::GetErpSupported () const
+{
+  return m_erpSupported;
+}
+
+void
+RegularWifiMac::SetErpSupported (bool enable)
+{
+  NS_LOG_FUNCTION (this);
+  m_erpSupported = enable;
+}
+
 void
 RegularWifiMac::SetCtsToSelfSupported (bool enable)
 {
@@ -607,6 +621,19 @@
 }
 
 void
+RegularWifiMac::SetShortSlotTimeSupported (bool enable)
+{
+  NS_LOG_FUNCTION (this << enable);
+  m_shortSlotTimeSupported = enable;
+}
+
+bool
+RegularWifiMac::GetShortSlotTimeSupported (void) const
+{
+  return m_shortSlotTimeSupported;
+}
+
+void
 RegularWifiMac::Enqueue (Ptr<const Packet> packet,
                          Mac48Address to, Mac48Address from)
 {
@@ -809,66 +836,66 @@
     .SetParent<WifiMac> ()
     .SetGroupName ("Wifi")
     .AddAttribute ("QosSupported",
-                   "This Boolean attribute is set to enable 802.11e/WMM-style QoS support at this STA",
+                   "This Boolean attribute is set to enable 802.11e/WMM-style QoS support at this STA.",
                    BooleanValue (false),
                    MakeBooleanAccessor (&RegularWifiMac::SetQosSupported,
                                         &RegularWifiMac::GetQosSupported),
                    MakeBooleanChecker ())
     .AddAttribute ("HtSupported",
-                   "This Boolean attribute is set to enable 802.11n support at this STA",
+                   "This Boolean attribute is set to enable 802.11n support at this STA.",
                    BooleanValue (false),
                    MakeBooleanAccessor (&RegularWifiMac::SetHtSupported,
                                         &RegularWifiMac::GetHtSupported),
                    MakeBooleanChecker ())
     .AddAttribute ("VhtSupported",
-                   "This Boolean attribute is set to enable 802.11ac support at this STA",
+                   "This Boolean attribute is set to enable 802.11ac support at this STA.",
                    BooleanValue (false),
                    MakeBooleanAccessor (&RegularWifiMac::SetVhtSupported,
                                         &RegularWifiMac::GetVhtSupported),
                    MakeBooleanChecker ())
     .AddAttribute ("CtsToSelfSupported",
-                   "Use CTS to Self when using a rate that is not in the basic set rate",
+                   "Use CTS to Self when using a rate that is not in the basic rate set.",
                    BooleanValue (false),
                    MakeBooleanAccessor (&RegularWifiMac::SetCtsToSelfSupported,
                                         &RegularWifiMac::GetCtsToSelfSupported),
                    MakeBooleanChecker ())
     .AddAttribute ("VO_MaxAmsduSize",
-                   "Maximum length in bytes of an A-MSDU for AC_VO access class",
+                   "Maximum length in bytes of an A-MSDU for AC_VO access class.",
                    UintegerValue (0),
                    MakeUintegerAccessor (&RegularWifiMac::SetVoMaxAmsduSize),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("VI_MaxAmsduSize",
-                   "Maximum length in bytes of an A-MSDU for AC_VI access class",
+                   "Maximum length in bytes of an A-MSDU for AC_VI access class.",
                    UintegerValue (0),
                    MakeUintegerAccessor (&RegularWifiMac::SetViMaxAmsduSize),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("BE_MaxAmsduSize",
-                   "Maximum length in bytes of an A-MSDU for AC_BE access class",
+                   "Maximum length in bytes of an A-MSDU for AC_BE access class.",
                    UintegerValue (0),
                    MakeUintegerAccessor (&RegularWifiMac::SetBeMaxAmsduSize),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("BK_MaxAmsduSize",
-                   "Maximum length in bytes of an A-MSDU for AC_BK access class",
+                   "Maximum length in bytes of an A-MSDU for AC_BK access class.",
                    UintegerValue (0),
                    MakeUintegerAccessor (&RegularWifiMac::SetBkMaxAmsduSize),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("VO_MaxAmpduSize",
-                   "Maximum length in bytes of an A-MPDU for AC_VO access class",
+                   "Maximum length in bytes of an A-MPDU for AC_VO access class.",
                    UintegerValue (0),
                    MakeUintegerAccessor (&RegularWifiMac::SetVoMaxAmpduSize),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("VI_MaxAmpduSize",
-                   "Maximum length in bytes of an A-MPDU for AC_VI access class",
+                   "Maximum length in bytes of an A-MPDU for AC_VI access class.",
                    UintegerValue (65535),
                    MakeUintegerAccessor (&RegularWifiMac::SetViMaxAmpduSize),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("BE_MaxAmpduSize",
-                   "Maximum length in bytes of an A-MPDU for AC_BE access class",
+                   "Maximum length in bytes of an A-MPDU for AC_BE access class.",
                    UintegerValue (65535),
                    MakeUintegerAccessor (&RegularWifiMac::SetBeMaxAmpduSize),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("BK_MaxAmpduSize",
-                   "Maximum length in bytes of an A-MPDU for AC_BK access class",
+                   "Maximum length in bytes of an A-MPDU for AC_BK access class.",
                    UintegerValue (0),
                    MakeUintegerAccessor (&RegularWifiMac::SetBkMaxAmpduSize),
                    MakeUintegerChecker<uint32_t> ())
@@ -928,36 +955,43 @@
                    UintegerValue (0),
                    MakeUintegerAccessor (&RegularWifiMac::SetBkBlockAckInactivityTimeout),
                    MakeUintegerChecker<uint16_t> ())
-    .AddAttribute ("DcaTxop", "The DcaTxop object",
+    .AddAttribute ("ShortSlotTimeSupported",
+                   "Whether or not short slot time is supported (only used by ERP APs or STAs).",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&WifiMac::GetShortSlotTimeSupported,
+                                        &WifiMac::SetShortSlotTimeSupported),
+                   MakeBooleanChecker ())
+    .AddAttribute ("DcaTxop",
+                   "The DcaTxop object.",
                    PointerValue (),
                    MakePointerAccessor (&RegularWifiMac::GetDcaTxop),
                    MakePointerChecker<DcaTxop> ())
     .AddAttribute ("VO_EdcaTxopN",
-                   "Queue that manages packets belonging to AC_VO access class",
+                   "Queue that manages packets belonging to AC_VO access class.",
                    PointerValue (),
                    MakePointerAccessor (&RegularWifiMac::GetVOQueue),
                    MakePointerChecker<EdcaTxopN> ())
     .AddAttribute ("VI_EdcaTxopN",
-                   "Queue that manages packets belonging to AC_VI access class",
+                   "Queue that manages packets belonging to AC_VI access class.",
                    PointerValue (),
                    MakePointerAccessor (&RegularWifiMac::GetVIQueue),
                    MakePointerChecker<EdcaTxopN> ())
     .AddAttribute ("BE_EdcaTxopN",
-                   "Queue that manages packets belonging to AC_BE access class",
+                   "Queue that manages packets belonging to AC_BE access class.",
                    PointerValue (),
                    MakePointerAccessor (&RegularWifiMac::GetBEQueue),
                    MakePointerChecker<EdcaTxopN> ())
     .AddAttribute ("BK_EdcaTxopN",
-                   "Queue that manages packets belonging to AC_BK access class",
+                   "Queue that manages packets belonging to AC_BK access class.",
                    PointerValue (),
                    MakePointerAccessor (&RegularWifiMac::GetBKQueue),
                    MakePointerChecker<EdcaTxopN> ())
     .AddTraceSource ("TxOkHeader",
-                     "The header of successfully transmitted packet",
+                     "The header of successfully transmitted packet.",
                      MakeTraceSourceAccessor (&RegularWifiMac::m_txOkCallback),
                      "ns3::WifiMacHeader::TracedCallback")
     .AddTraceSource ("TxErrHeader",
-                     "The header of unsuccessfully transmitted packet",
+                     "The header of unsuccessfully transmitted packet.",
                      MakeTraceSourceAccessor (&RegularWifiMac::m_txErrCallback),
                      "ns3::WifiMacHeader::TracedCallback")
   ;
@@ -975,16 +1009,18 @@
     case WIFI_PHY_STANDARD_80211ac:
       SetVhtSupported (true);
     case WIFI_PHY_STANDARD_80211n_5GHZ:
-    case WIFI_PHY_STANDARD_80211n_2_4GHZ:
       SetHtSupported (true);
     case WIFI_PHY_STANDARD_holland:
     case WIFI_PHY_STANDARD_80211a:
-    case WIFI_PHY_STANDARD_80211g:
     case WIFI_PHY_STANDARD_80211_10MHZ:
     case WIFI_PHY_STANDARD_80211_5MHZ:
       cwmin = 15;
       cwmax = 1023;
       break;
+    case WIFI_PHY_STANDARD_80211n_2_4GHZ:
+      SetHtSupported (true);
+    case WIFI_PHY_STANDARD_80211g:
+      m_erpSupported = true;
     case WIFI_PHY_STANDARD_80211b:
       cwmin = 31;
       cwmax = 1023;
@@ -993,15 +1029,21 @@
       NS_FATAL_ERROR ("Unsupported WifiPhyStandard in RegularWifiMac::FinishConfigureStandard ()");
     }
 
+  ConfigureContentionWindow (cwmin, cwmax);
+}
+
+void
+RegularWifiMac::ConfigureContentionWindow (uint32_t cwMin, uint32_t cwMax)
+{
   //The special value of AC_BE_NQOS which exists in the Access
   //Category enumeration allows us to configure plain old DCF.
-  ConfigureDcf (m_dca, cwmin, cwmax, AC_BE_NQOS);
+  ConfigureDcf (m_dca, cwMin, cwMax, AC_BE_NQOS);
 
   //Now we configure the EDCA functions
   for (EdcaQueues::iterator i = m_edca.begin (); i != m_edca.end (); ++i)
-    {
-      ConfigureDcf (i->second, cwmin, cwmax, i->first);
-    }
+  {
+    ConfigureDcf (i->second, cwMin, cwMax, i->first);
+  }
 }
 
 void
--- a/src/wifi/model/regular-wifi-mac.h	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/regular-wifi-mac.h	Wed Feb 17 22:40:00 2016 +0100
@@ -119,7 +119,6 @@
    *               false otherwise
    */
   void SetCtsToSelfSupported (bool enable);
-
   /**
    * Return whether the device supports CTS-to-self
    * capability.
@@ -128,6 +127,22 @@
    *         false otherwise.
    */
   bool GetCtsToSelfSupported () const;
+
+  /**
+   * Enable or disable short slot time feature.
+   *
+   * \param enable true if short slot time is to be supported,
+   *               false otherwise
+   */
+  virtual void SetShortSlotTimeSupported (bool enable);
+  /**
+   * \return whether the device supports short slot time capability.
+   *
+   * \return true if short slot time is supported,
+   *         false otherwise.
+   */
+  virtual bool GetShortSlotTimeSupported (void) const;
+
   /**
    * \return the MAC address associated to this MAC layer.
    */
@@ -313,6 +328,15 @@
    * chain up to this implementation to deal with the remainder.
    */
   virtual void FinishConfigureStandard (enum WifiPhyStandard standard);
+  
+  /**
+   * \param cwMin the minimum congestion window size
+   * \param cwMax the maximum congestion window size
+   *
+   * This method is called to set the minimum and the maximum
+   * contention window size.
+   */
+  void ConfigureContentionWindow (uint32_t cwMin, uint32_t cwMax);
 
   /**
    * This method is invoked by a subclass to specify what type of
@@ -455,6 +479,24 @@
    * \return true if VHT is supported, false otherwise
    */
   bool GetVhtSupported () const;
+  
+  /**
+   * This Boolean is set \c true iff this WifiMac is to model
+   * 802.11g. It is exposed through the attribute system.
+   */
+  bool m_erpSupported;
+  /**
+   * Enable or disable ERP support for the device.
+   *
+   * \param enable whether ERP is supported
+   */
+  void SetErpSupported (bool enable);
+  /**
+   * Return whether the device supports ERP.
+   *
+   * \return true if ERP is supported, false otherwise
+   */
+  bool GetErpSupported () const;
 
 
 private:
@@ -505,6 +547,8 @@
 
   TracedCallback<const WifiMacHeader &> m_txOkCallback;
   TracedCallback<const WifiMacHeader &> m_txErrCallback;
+  
+  bool m_shortSlotTimeSupported;
 };
 
 } //namespace ns3
--- a/src/wifi/model/rraa-wifi-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/rraa-wifi-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -309,7 +309,16 @@
       //avoid to use legacy rate adaptation algorithms for IEEE 802.11n/ac
       channelWidth = 20;
     }
-  return WifiTxVector (GetSupported (st, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (st), false, 1, 0, channelWidth, GetAggregation (station), false);
+  WifiTxVector rtsTxVector;
+  if (GetUseProtection () == false)
+    {
+      rtsTxVector = WifiTxVector (GetSupported (st, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (st), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  else
+    {
+      rtsTxVector = WifiTxVector (GetNonErpSupported (st, 0), GetDefaultTxPowerLevel (), GetShortRetryCount (st), false, 1, 0, channelWidth, GetAggregation (station), false);
+    }
+  return rtsTxVector;
 }
 
 bool
--- a/src/wifi/model/sta-wifi-mac.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/sta-wifi-mac.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -489,6 +489,7 @@
     {
       MgtBeaconHeader beacon;
       packet->RemoveHeader (beacon);
+      CapabilityInformation capabilities = beacon.GetCapabilities ();
       bool goodBeacon = false;
       if (GetSsid ().IsBroadcast ()
           || beacon.GetSsid ().IsEqual (GetSsid ()))
@@ -513,6 +514,34 @@
           Time delay = MicroSeconds (beacon.GetBeaconIntervalUs () * m_maxMissedBeacons);
           RestartBeaconWatchdog (delay);
           SetBssid (hdr->GetAddr3 ());
+          bool isShortPreambleEnabled = capabilities.IsShortPreamble ();
+          if (m_erpSupported)
+            {
+              ErpInformation erpInformation = beacon.GetErpInformation ();
+              isShortPreambleEnabled &= !erpInformation.GetBarkerPreambleMode ();
+              if (erpInformation.GetUseProtection() == true)
+                {
+                  m_stationManager->SetUseProtection (true);
+                }
+              else
+                {
+                  m_stationManager->SetUseProtection (false);
+                }
+              if (capabilities.IsShortSlotTime () == true)
+                {
+                  //enable short slot time and set cwMin to 15
+                  SetSlot (MicroSeconds (9));
+                  ConfigureContentionWindow (15, 1023);
+                }
+              else
+                {
+                  //disable short slot time and set cwMin to 31
+                  SetSlot (MicroSeconds (20));
+                  ConfigureContentionWindow (31, 1023);
+                }
+            }
+          m_stationManager->SetShortPreambleEnabled (isShortPreambleEnabled);
+          m_stationManager->SetShortSlotTimeEnabled (capabilities.IsShortSlotTime ());
         }
       if (goodBeacon && m_state == BEACON_MISSED)
         {
@@ -527,6 +556,7 @@
         {
           MgtProbeResponseHeader probeResp;
           packet->RemoveHeader (probeResp);
+          CapabilityInformation capabilities = probeResp.GetCapabilities ();
           if (!probeResp.GetSsid ().IsEqual (GetSsid ()))
             {
               //not a probe resp for our ssid.
@@ -553,6 +583,34 @@
                     }
                 }
             }
+            
+          bool isShortPreambleEnabled = capabilities.IsShortPreamble ();
+          if (m_erpSupported)
+            {
+              ErpInformation erpInformation = probeResp.GetErpInformation ();
+              if (erpInformation.GetUseProtection() == true)
+                {
+                  m_stationManager->SetUseProtection (true);
+                }
+              else
+                {
+                  m_stationManager->SetUseProtection (false);
+                }
+              if (capabilities.IsShortSlotTime () == true)
+                {
+                  //enable short slot time and set cwMin to 15
+                  SetSlot (MicroSeconds (9));
+                  ConfigureContentionWindow (15, 1023);
+                }
+              else
+                {
+                  //disable short slot time and set cwMin to 31
+                  SetSlot (MicroSeconds (20));
+                  ConfigureContentionWindow (31, 1023);
+                }
+            }
+          m_stationManager->SetShortPreambleEnabled (isShortPreambleEnabled);
+          m_stationManager->SetShortSlotTimeEnabled (capabilities.IsShortSlotTime ());
           SetBssid (hdr->GetAddr3 ());
           Time delay = MicroSeconds (probeResp.GetBeaconIntervalUs () * m_maxMissedBeacons);
           RestartBeaconWatchdog (delay);
@@ -571,8 +629,6 @@
         {
           MgtAssocResponseHeader assocResp;
           packet->RemoveHeader (assocResp);
-          CapabilityInformation capabilities = assocResp.GetCapabilities ();
-          m_stationManager->AddSupportedPlcpPreamble (hdr->GetAddr2 (), capabilities.IsShortPreamble ());
           if (m_assocRequestEvent.IsRunning ())
             {
               m_assocRequestEvent.Cancel ();
@@ -581,7 +637,28 @@
             {
               SetState (ASSOCIATED);
               NS_LOG_DEBUG ("assoc completed");
+              CapabilityInformation capabilities = assocResp.GetCapabilities ();
               SupportedRates rates = assocResp.GetSupportedRates ();
+              bool isShortPreambleEnabled = capabilities.IsShortPreamble ();
+              if (m_erpSupported)
+                {
+                  ErpInformation erpInformation = assocResp.GetErpInformation ();
+                  isShortPreambleEnabled &= !erpInformation.GetBarkerPreambleMode ();
+                  if (m_stationManager->GetShortSlotTimeEnabled ())
+                    {
+                      //enable short slot time and set cwMin to 15
+                      SetSlot (MicroSeconds (9));
+                      ConfigureContentionWindow (15, 1023);
+                    }
+                  else
+                    {
+                      //disable short slot time and set cwMin to 31
+                      SetSlot (MicroSeconds (20));
+                      ConfigureContentionWindow (31, 1023);
+                    }
+                }
+              m_stationManager->SetShortPreambleEnabled (isShortPreambleEnabled);
+              m_stationManager->SetShortSlotTimeEnabled (capabilities.IsShortSlotTime ());
               if (m_htSupported)
                 {
                   HtCapabilities htcapabilities = assocResp.GetHtCapabilities ();
@@ -674,7 +751,8 @@
 StaWifiMac::GetCapabilities (void) const
 {
   CapabilityInformation capabilities;
-  capabilities.SetShortPreamble (m_phy->GetShortPlcpPreamble ());
+  capabilities.SetShortPreamble (m_phy->GetShortPlcpPreambleSupported () || m_erpSupported);
+  capabilities.SetShortSlotTime (GetShortSlotTimeSupported () && m_erpSupported);
   return capabilities;
 }
 
--- a/src/wifi/model/wifi-mac.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/wifi-mac.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -21,6 +21,7 @@
 #include "wifi-mac.h"
 #include "dcf.h"
 #include "ns3/uinteger.h"
+#include "ns3/boolean.h"
 #include "ns3/trace-source-accessor.h"
 
 namespace ns3 {
@@ -351,10 +352,9 @@
 {
   SetSifs (MicroSeconds (10));
   // Slot time defaults to the "long slot time" of 20 us in the standard
-  // according to mixed 802.11b/g deployments.  Short slot time is supported
-  // if the user sets the slot to 9 us *after* calling Configure80211g().
-  // The other parameters below should also be adjusted accordingly as they
-  // depend on slot time.
+  // according to mixed 802.11b/g deployments.  Short slot time is enabled
+  // if the user sets the ShortSlotTimeSupported flag to true and when the BSS
+  // consists of only ERP STAs capable of supporting this option.
   SetSlot (MicroSeconds (20));
   SetEifsNoDifs (MicroSeconds (10 + 304));
   SetPifs (MicroSeconds (10 + 20));
--- a/src/wifi/model/wifi-mac.h	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/wifi-mac.h	Wed Feb 17 22:40:00 2016 +0100
@@ -65,10 +65,9 @@
    * \param pifs the pifs duration.
    */
   virtual void SetPifs (Time pifs) = 0;
-/**
+  /**
    * \param rifs the rifs duration.
    */
-
   virtual void SetRifs (Time rifs) = 0;
   /**
    * \param ctsTimeout the duration of a CTS timeout.
@@ -84,6 +83,23 @@
    * Unused for now.
    */
   void SetMaxPropagationDelay (Time delay);
+  /**
+   * \param ssid the current ssid of this MAC layer.
+   */
+  virtual void SetSsid (Ssid ssid) = 0;
+  /**
+   * \param enable true if short slot time is to be supported,
+   *               false otherwise
+   */
+  virtual void SetShortSlotTimeSupported (bool enable) = 0;
+  /**
+   * \brief Sets the interface in promiscuous mode.
+   *
+   * Enables promiscuous mode on the interface. Note that any further
+   * filtering on the incoming frame path may affect the overall
+   * behavior.
+   */
+  virtual void SetPromisc (void) = 0;
 
   /**
    * \return the current RIFS duration.
@@ -138,21 +154,13 @@
    */
   virtual void SetAddress (Mac48Address address) = 0;
   /**
-   * \param ssid the current ssid of this MAC layer.
-   */
-  virtual void SetSsid (Ssid ssid) = 0;
-  /**
    * \return the bssid of the network this device belongs to.
    */
   virtual Mac48Address GetBssid (void) const = 0;
   /**
-   * \brief Sets the interface in promiscuous mode.
-   *
-   * Enables promiscuous mode on the interface. Note that any further
-   * filtering on the incoming frame path may affect the overall
-   * behavior.
+   * \return whether the device supports short slot time capability.
    */
-  virtual void SetPromisc (void) = 0;
+  virtual bool GetShortSlotTimeSupported (void) const = 0;
 
   /**
    * \param packet the packet to send.
--- a/src/wifi/model/wifi-phy.h	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/wifi-phy.h	Wed Feb 17 22:40:00 2016 +0100
@@ -1258,13 +1258,13 @@
    */
   virtual bool GetGreenfield (void) const = 0;
   /**
-   * \param shortPreamble Enable or disable short PLCP preamble
+   * \param preamble sets whether short PLCP preamble is supported or not
    */
-  virtual void SetShortPlcpPreamble (bool shortPreamble) = 0;
+  virtual void SetShortPlcpPreambleSupported (bool preamble) = 0;
   /**
    * \return true if short PLCP preamble is supported, false otherwise
    */
-  virtual bool GetShortPlcpPreamble (void) const = 0;
+  virtual bool GetShortPlcpPreambleSupported (void) const = 0;
   /**
    * \return the channel width
    */
--- a/src/wifi/model/wifi-remote-station-manager.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/wifi-remote-station-manager.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -27,6 +27,7 @@
 #include "ns3/boolean.h"
 #include "ns3/double.h"
 #include "ns3/uinteger.h"
+#include "ns3/enum.h"
 #include "ns3/wifi-phy.h"
 #include "ns3/wifi-mac.h"
 #include "ns3/trace-source-accessor.h"
@@ -329,6 +330,13 @@
                    UintegerValue (0),
                    MakeUintegerAccessor (&WifiRemoteStationManager::m_defaultTxPowerLevel),
                    MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("ProtectionMode",
+                   "Protection mode used when non-ERP STAs are connected to an ERP AP: Rts-Cts or Cts-To-Self",
+                   EnumValue (WifiRemoteStationManager::CTS_TO_SELF),
+                   MakeEnumAccessor (&WifiRemoteStationManager::SetProtectionMode,
+                                     &WifiRemoteStationManager::GetProtectionMode),
+                   MakeEnumChecker (WifiRemoteStationManager::RTS_CTS, "Rts-Cts",
+                                    WifiRemoteStationManager::CTS_TO_SELF, "Cts-To-Self"))
     .AddTraceSource ("MacTxRtsFailed",
                      "The transmission of a RTS by the MAC layer has failed",
                      MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxRtsFailed),
@@ -351,7 +359,10 @@
 
 WifiRemoteStationManager::WifiRemoteStationManager ()
   : m_htSupported (false),
-    m_vhtSupported (false)
+    m_vhtSupported (false),
+    m_useProtection (false),
+    m_shortPreambleEnabled (false),
+    m_shortSlotTimeEnabled (false)
 {
 }
 
@@ -430,6 +441,42 @@
   DoSetFragmentationThreshold (threshold);
 }
 
+void
+WifiRemoteStationManager::SetProtectionMode (WifiRemoteStationManager::ProtectionMode mode)
+{
+  m_protectionMode = mode;
+}
+
+void
+WifiRemoteStationManager::SetShortPreambleEnabled (bool enable)
+{
+  m_shortPreambleEnabled = enable;
+}
+
+void
+WifiRemoteStationManager::SetShortSlotTimeEnabled (bool enable)
+{
+  m_shortSlotTimeEnabled = enable;
+}
+
+bool
+WifiRemoteStationManager::GetShortSlotTimeEnabled (void) const
+{
+  return m_shortSlotTimeEnabled;
+}
+
+bool
+WifiRemoteStationManager::GetShortPreambleEnabled (void) const
+{
+  return m_shortPreambleEnabled;
+}
+
+WifiRemoteStationManager::ProtectionMode
+WifiRemoteStationManager::GetProtectionMode (void) const
+{
+  return m_protectionMode;
+}
+
 bool
 WifiRemoteStationManager::HasHtSupported (void) const
 {
@@ -494,6 +541,15 @@
 }
 
 void
+WifiRemoteStationManager::AddSupportedErpSlotTime (Mac48Address address, bool isShortSlotTimeSupported)
+{
+  NS_LOG_FUNCTION (this << address << isShortSlotTimeSupported);
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStationState *state = LookupState (address);
+  state->m_shortSlotTime = isShortSlotTimeSupported;
+}
+
+void
 WifiRemoteStationManager::AddSupportedMode (Mac48Address address, WifiMode mode)
 {
   NS_LOG_FUNCTION (this << address << mode);
@@ -540,6 +596,18 @@
 }
 
 bool
+WifiRemoteStationManager::GetShortPreambleSupported (Mac48Address address) const
+{
+  return LookupState (address)->m_shortPreamble;
+}
+
+bool
+WifiRemoteStationManager::GetShortSlotTimeSupported (Mac48Address address) const
+{
+  return LookupState (address)->m_shortSlotTime;
+}
+
+bool
 WifiRemoteStationManager::IsBrandNew (Mac48Address address) const
 {
   if (address.IsGroup ())
@@ -795,9 +863,17 @@
 
 bool
 WifiRemoteStationManager::NeedRts (Mac48Address address, const WifiMacHeader *header,
-                                   Ptr<const Packet> packet)
+                                   Ptr<const Packet> packet, WifiTxVector txVector)
 {
-  NS_LOG_FUNCTION (this << address << *header << packet);
+  WifiMode mode = txVector.GetMode ();
+  NS_LOG_FUNCTION (this << address << *header << packet << mode);
+  if (m_protectionMode == RTS_CTS
+      && mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM
+      && m_useProtection)
+    {
+      NS_LOG_DEBUG ("WifiRemoteStationManager::NeedRTS returning true to protect non-ERP stations");
+      return true;
+    }
   if (address.IsGroup ())
     {
       return false;
@@ -809,21 +885,19 @@
 bool
 WifiRemoteStationManager::NeedCtsToSelf (WifiTxVector txVector)
 {
-  NS_LOG_FUNCTION (this << txVector);
   WifiMode mode = txVector.GetMode ();
-  //search for the BSS Basic Rate set, if the used mode is in the basic set then there is no need for Cts To Self
-  for (WifiModeListIterator i = m_bssBasicRateSet.begin (); i != m_bssBasicRateSet.end (); i++)
+  NS_LOG_FUNCTION (this << mode);
+  if (m_protectionMode == CTS_TO_SELF
+      && mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM
+      && m_useProtection)
     {
-      if (mode == *i)
-        {
-          NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning false");
-          return false;
-        }
+      NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-ERP stations");
+      return true;
     }
-  if (HasHtSupported ())
+  else if (!m_useProtection)
     {
-      //search for the BSS Basic MCS set, if the used mode is in the basic set then there is no need for Cts To Self
-      for (WifiModeListIterator i = m_bssBasicMcsSet.begin (); i != m_bssBasicMcsSet.end (); i++)
+    //search for the BSS Basic Rate set, if the used mode is in the basic set then there is no need for Cts To Self
+      for (WifiModeListIterator i = m_bssBasicRateSet.begin (); i != m_bssBasicRateSet.end (); i++)
         {
           if (mode == *i)
             {
@@ -831,9 +905,34 @@
               return false;
             }
         }
+      if (HasHtSupported ())
+        {
+          //search for the BSS Basic MCS set, if the used mode is in the basic set then there is no need for Cts To Self
+          for (WifiModeListIterator i = m_bssBasicMcsSet.begin (); i != m_bssBasicMcsSet.end (); i++)
+            {
+              if (mode == *i)
+                {
+                  NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning false");
+                  return false;
+                }
+            }
+        }
+      NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning true");
+      return true;
     }
-  NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning true");
-  return true;
+  return false;
+}
+
+void
+WifiRemoteStationManager::SetUseProtection (bool enable)
+{
+  m_useProtection = enable;
+}
+
+bool
+WifiRemoteStationManager::GetUseProtection (void) const
+{
+  return m_useProtection;
 }
 
 bool
@@ -1321,7 +1420,6 @@
   state->m_channelWidth = m_wifiPhy->GetChannelWidth ();
   state->m_shortGuardInterval = m_wifiPhy->GetGuardInterval ();
   state->m_greenfield = m_wifiPhy->GetGreenfield ();
-  state->m_shortPreamble = m_wifiPhy->GetShortPlcpPreamble ();
   state->m_rx = 1;
   state->m_tx = 1;
   state->m_ness = 0;
@@ -1418,12 +1516,6 @@
   return LookupState (address)->m_greenfield;
 }
 
-bool
-WifiRemoteStationManager::GetShortPreambleSupported (Mac48Address address) const
-{
-  return LookupState (address)->m_shortPreamble;
-}
-
 WifiMode
 WifiRemoteStationManager::GetDefaultMode (void) const
 {
@@ -1479,10 +1571,50 @@
 WifiMode
 WifiRemoteStationManager::GetBasicMode (uint32_t i) const
 {
-  NS_ASSERT (i < m_bssBasicRateSet.size ());
+  NS_ASSERT (i < GetNBasicModes ());
   return m_bssBasicRateSet[i];
 }
 
+uint32_t
+WifiRemoteStationManager::GetNNonErpBasicModes (void) const
+{
+  uint32_t size = 0;
+  for (WifiModeListIterator i = m_bssBasicRateSet.begin (); i != m_bssBasicRateSet.end (); i++)
+  {
+    if (i->GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM)
+      {
+        continue;
+      }
+    size++;
+  }
+  return size;
+}
+
+WifiMode
+WifiRemoteStationManager::GetNonErpBasicMode (uint32_t i) const
+{
+  NS_ASSERT (i < GetNNonErpBasicModes ());
+  uint32_t index = 0;
+  bool found = false;
+  for (WifiModeListIterator j = m_bssBasicRateSet.begin (); j != m_bssBasicRateSet.end (); )
+  {
+    if (i == index)
+      {
+        found = true;
+      }
+    if (j->GetModulationClass () != WIFI_MOD_CLASS_ERP_OFDM)
+      {
+        if (found)
+          {
+            break;
+          }
+      }
+    index++;
+    j++;
+  }
+  return m_bssBasicRateSet[index];
+}
+
 void
 WifiRemoteStationManager::AddBasicMcs (WifiMode mcs)
 {
@@ -1506,7 +1638,7 @@
 WifiMode
 WifiRemoteStationManager::GetBasicMcs (uint32_t i) const
 {
-  NS_ASSERT (i < m_bssBasicMcsSet.size ());
+  NS_ASSERT (i < GetNBasicMcs ());
   return m_bssBasicMcsSet[i];
 }
 
@@ -1565,6 +1697,34 @@
   return station->m_state->m_operationalMcsSet[i];
 }
 
+WifiMode
+WifiRemoteStationManager::GetNonErpSupported (const WifiRemoteStation *station, uint32_t i) const
+{
+  NS_ASSERT (i < GetNNonErpSupported (station));
+  //IEEE 802.11g standard defines that if the protection mechanism is enabled, Rts, Cts and Cts-To-Self
+  //frames should select a rate in the BSSBasicRateSet that corresponds to an 802.11b basic rate.
+  //This is a implemented here to avoid changes in every RAA, but should maybe be moved in case it breaks standard rules.
+  uint32_t index = 0;
+  bool found = false;
+  for (WifiModeListIterator j = station->m_state->m_operationalRateSet.begin (); j != station->m_state->m_operationalRateSet.end (); )
+  {
+    if (i == index)
+      {
+        found = true;
+      }
+    if (j->GetModulationClass () != WIFI_MOD_CLASS_ERP_OFDM)
+      {
+        if (found)
+          {
+            break;
+          }
+      }
+    index++;
+    j++;
+  }
+  return station->m_state->m_operationalRateSet[index];
+}
+
 uint32_t
 WifiRemoteStationManager::GetChannelWidth (const WifiRemoteStation *station) const
 {
@@ -1584,12 +1744,6 @@
 }
 
 bool
-WifiRemoteStationManager::GetShortPreamble (const WifiRemoteStation *station) const
-{
-  return station->m_state->m_shortPreamble;
-}
-
-bool
 WifiRemoteStationManager::GetAggregation (const WifiRemoteStation *station) const
 {
   return station->m_state->m_aggregation;
@@ -1655,6 +1809,21 @@
   return station->m_state->m_operationalMcsSet.size ();
 }
 
+uint32_t
+WifiRemoteStationManager::GetNNonErpSupported (const WifiRemoteStation *station) const
+{
+  uint32_t size = 0;
+  for (WifiModeListIterator i = station->m_state->m_operationalRateSet.begin (); i != station->m_state->m_operationalRateSet.end (); i++)
+  {
+    if (i->GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM)
+      {
+        continue;
+      }
+    size++;
+  }
+  return size;
+}
+
 void
 WifiRemoteStationManager::SetDefaultTxPowerLevel (uint8_t txPower)
 {
--- a/src/wifi/model/wifi-remote-station-manager.h	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/wifi-remote-station-manager.h	Wed Feb 17 22:40:00 2016 +0100
@@ -92,6 +92,12 @@
 
   WifiRemoteStationManager ();
   virtual ~WifiRemoteStationManager ();
+  
+  enum ProtectionMode
+  {
+    RTS_CTS = 0,
+    CTS_TO_SELF
+  };
 
   /**
    * Set up PHY associated with this device since it is the object that
@@ -200,6 +206,57 @@
    * \return true if VHT capability support is enabled, false otherwise
    */
   bool HasVhtSupported (void) const;
+  /**
+   * Sets the protection mode.
+   *
+   * \param mode the protection mode
+   */
+  void SetProtectionMode (ProtectionMode mode);
+  /**
+   * Return the protection mode.
+   *
+   * \return the protection mode
+   */
+  ProtectionMode GetProtectionMode (void) const;
+  /**
+   * Enable or disable protection for non-ERP stations.
+   *
+   * \param enable enable or disable protection for non-ERP stations
+   */
+  void SetUseProtection (bool enable);
+  /**
+   * Return whether the device supports protection of non-ERP stations.
+   *
+   * \return true if protection for non-ERP stations is enabled, 
+   *         false otherwise
+   */
+  bool GetUseProtection (void) const;
+  /**
+   * Enable or disable short PLCP preambles.
+   *
+   * \param enable enable or disable short PLCP preambles
+   */
+  void SetShortPreambleEnabled (bool enable);
+  /**
+   * Return whether the device uses short PLCP preambles.
+   *
+   * \return true if short PLCP preambles are enabled,
+   *         false otherwise
+   */
+  bool GetShortPreambleEnabled (void) const;
+  /**
+   * Enable or disable short slot time.
+   *
+   * \param enable enable or disable short slot time
+   */
+  void SetShortSlotTimeEnabled (bool enable);
+  /**
+   * Return whether the device uses short slot time.
+   *
+   * \return true if short slot time is enabled,
+   *         false otherwise
+   */
+  bool GetShortSlotTimeEnabled (void) const;
 
   /**
    * Reset the station, invoked in a STA upon dis-association or in an AP upon reboot.
@@ -235,6 +292,20 @@
    */
   WifiMode GetBasicMode (uint32_t i) const;
   /**
+   * Return the number of non-ERP basic modes we support.
+   *
+   * \return the number of basic modes we support
+   */
+  uint32_t GetNNonErpBasicModes (void) const;
+  /**
+   * Return a basic mode from the set of basic modes that is not an ERP mode.
+   *
+   * \param i index of the basic mode in the basic mode set
+   *
+   * \return the basic mode at the given index
+   */
+  WifiMode GetNonErpBasicMode (uint32_t i) const;
+  /**
    * Return whether the station supports Greenfield or not.
    *
    * \param address the address of the station
@@ -253,6 +324,15 @@
    */
   bool GetShortPreambleSupported (Mac48Address address) const;
   /**
+   * Return whether the station supports short ERP slot time or not.
+   *
+   * \param address the address of the station
+   *
+   * \return true if short ERP slot time is supported by the station,
+   *         false otherwise
+   */
+  bool GetShortSlotTimeSupported (Mac48Address address) const;
+  /**
    * Add a given Modulation and Coding Scheme (MCS) index to
    * the set of basic MCS.
    *
@@ -321,7 +401,6 @@
    * \param address the address of the station being recorded
    */
   void AddAllSupportedModes (Mac48Address address);
-
   /**
    * Record whether the short PLCP preamble is supported by the station.
    *
@@ -329,7 +408,13 @@
    * \param isShortPreambleSupported whether or not short PLCP preamble is supported by the station
    */
   void AddSupportedPlcpPreamble (Mac48Address address, bool isShortPreambleSupported);
-
+  /**
+   * Record whether the short ERP slot time is supported by the station.
+   *
+   * \param address the address of the station
+   * \param isShortSlotTimeSupported whether or not short ERP slot time is supported by the station
+   */
+  void AddSupportedErpSlotTime (Mac48Address address, bool isShortSlotTimeSupported);
   /**
    * Return whether the station state is brand new.
    *
@@ -511,12 +596,13 @@
    * \param address remote address
    * \param header MAC header
    * \param packet the packet to send
+   * \param txVector the TXVECTOR of the packet to send
    *
    * \return true if we want to use an RTS/CTS handshake for this
    *         packet before sending it, false otherwise.
    */
   bool NeedRts (Mac48Address address, const WifiMacHeader *header,
-                Ptr<const Packet> packet);
+                Ptr<const Packet> packet, WifiTxVector txVector);
   /**
    * Return if we need to do Cts-to-self before sending a DATA.
    *
@@ -685,6 +771,23 @@
    */
   uint32_t GetNMcsSupported (const WifiRemoteStation *station) const;
   /**
+   * Return whether non-ERP mode associated with the specified station at the specified index.
+   *
+   * \param station the station being queried
+   * \param i the index
+   *
+   * \return WifiMode at the given index of the specified station
+   */
+  WifiMode GetNonErpSupported (const WifiRemoteStation *station, uint32_t i) const;
+  /**
+   * Return the number of non-ERP modes supported by the given station.
+   *
+   * \param station the station being queried
+   *
+   * \return the number of non-ERP modes supported by the given station
+   */
+  uint32_t GetNNonErpSupported (const WifiRemoteStation *station) const;
+  /**
    * Return the channel width supported by the station.
    *
    * \param station the station being queried
@@ -728,15 +831,7 @@
    *         false otherwise
    */
   bool GetGreenfield (const WifiRemoteStation *station) const;
-  /**
-   * Return whether the station supports short PLCP preamble or not.
-   *
-   * \param station the station being queried
-   *
-   * \return true if short PLCP preamble is supported by the station,
-   *         false otherwise
-   */
-  bool GetShortPreamble (const WifiRemoteStation *station) const;
+
   /**
    * Return the number of receive antennas the station has.
    *
@@ -1081,6 +1176,10 @@
   uint32_t m_nextFragmentationThreshold;  //!< Threshold for fragmentation that will be used for the next transmission
   uint8_t m_defaultTxPowerLevel;  //!< Default tranmission power level
   WifiMode m_nonUnicastMode;  //!< Transmission mode for non-unicast DATA frames
+  bool m_useProtection; //!< flag if protection for non-ERP stations against ERP transmissions is enabled
+  bool m_shortPreambleEnabled; //!< flag if short PLCP preamble is enabled
+  bool m_shortSlotTimeEnabled; //!< flag if short slot time is enabled
+  ProtectionMode m_protectionMode; //!< Protection mode for ERP stations when non-ERP stations are detected
 
   /**
    * The trace source fired when the transmission of a single RTS has failed
@@ -1137,10 +1236,11 @@
   uint32_t m_rx;              //!< Number of RX antennas of the remote station
   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_stbc;                //!< Flag if STBC is supported by the remote station
   bool m_aggregation;         //!< Flag if MPDU aggregation is used by the remote station
-  bool m_greenfield;          //!< Flag if greenfield is used by the remote station
-  bool m_shortPreamble;       //!< Flag if short PLCP preamble is used by the remote station
+  bool m_greenfield;          //!< Flag if greenfield is supported by the remote station
+  bool m_shortPreamble;       //!< Flag if short PLCP preamble is supported by the remote station
+  bool m_shortSlotTime;       //!< Flag if short ERP slot time is supported by the remote station
 };
 
 /**
--- a/src/wifi/model/yans-wifi-phy.cc	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/yans-wifi-phy.cc	Wed Feb 17 22:40:00 2016 +0100
@@ -144,7 +144,8 @@
                                          &YansWifiPhy::SetNumberOfReceiveAntennas),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("ShortGuardEnabled",
-                   "Whether or not short guard interval is enabled.",
+                   "Whether or not short guard interval is enabled."
+                   "This parameter is only valuable for 802.11n/ac STAs and APs.",
                    BooleanValue (false),
                    MakeBooleanAccessor (&YansWifiPhy::GetGuardInterval,
                                         &YansWifiPhy::SetGuardInterval),
@@ -162,16 +163,19 @@
                                         &YansWifiPhy::SetStbc),
                    MakeBooleanChecker ())
     .AddAttribute ("GreenfieldEnabled",
-                   "Whether or not Greenfield is enabled.",
+                   "Whether or not Greenfield is enabled."
+                   "This parameter is only valuable for 802.11n STAs and APs.",
                    BooleanValue (false),
                    MakeBooleanAccessor (&YansWifiPhy::GetGreenfield,
                                         &YansWifiPhy::SetGreenfield),
                    MakeBooleanChecker ())
-    .AddAttribute ("ShortPlcpPreambleEnabled",
-                   "Whether or not short PLCP preamble is enabled.",
+    .AddAttribute ("ShortPlcpPreambleSupported",
+                   "Whether or not short PLCP preamble is supported."
+                   "This parameter is only valuable for 802.11b STAs and APs."
+                   "Note: 802.11g APs and STAs always support short PLCP preamble.",
                    BooleanValue (false),
-                   MakeBooleanAccessor (&YansWifiPhy::GetShortPlcpPreamble,
-                                        &YansWifiPhy::SetShortPlcpPreamble),
+                   MakeBooleanAccessor (&YansWifiPhy::GetShortPlcpPreambleSupported,
+                                        &YansWifiPhy::SetShortPlcpPreambleSupported),
                    MakeBooleanChecker ())
     .AddAttribute ("ChannelWidth",
                    "Whether 5MHz, 10MHz, 20MHz, 22MHz, 40MHz, 80 MHz or 160 MHz.",
@@ -1305,15 +1309,15 @@
 }
 
 bool
-YansWifiPhy::GetShortPlcpPreamble (void) const
+YansWifiPhy::GetShortPlcpPreambleSupported (void) const
 {
-  return m_plcpPreamble;
+  return m_shortPreamble;
 }
 
 void
-YansWifiPhy::SetShortPlcpPreamble (bool preamble)
+YansWifiPhy::SetShortPlcpPreambleSupported (bool enable)
 {
-  m_plcpPreamble = preamble;
+  m_shortPreamble = enable;
 }
 
 void
--- a/src/wifi/model/yans-wifi-phy.h	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/model/yans-wifi-phy.h	Wed Feb 17 22:40:00 2016 +0100
@@ -388,15 +388,15 @@
   /**
    * Enable or disable short PLCP preamble.
    *
-   * \param sets short PLCP preamble is supported or not
+   * \param preamble sets whether short PLCP preamble is supported or not
    */
-  virtual void SetShortPlcpPreamble (bool preamble);
+  virtual void SetShortPlcpPreambleSupported (bool preamble);
   /**
    * Return whether short PLCP preamble is supported.
    *
    * \returns if short PLCP preamble is supported or not
    */
-  virtual bool GetShortPlcpPreamble (void) const;
+  virtual bool GetShortPlcpPreambleSupported (void) const;
   /**
    * Return channel width.
    *
@@ -538,7 +538,7 @@
   bool     m_greenfield;            //!< Flag if GreenField format is supported
   bool     m_guardInterval;         //!< Flag if short guard interval is used
   uint32_t m_channelWidth;          //!< Channel width
-  bool     m_plcpPreamble;          //!< Flag if short PLCP preamble is used
+  bool     m_shortPreamble;         //!< Flag if short PLCP preamble is supported
 
   /**
    * This vector holds the set of transmission modes that this
--- a/src/wifi/wscript	Wed Feb 17 11:22:02 2016 +0100
+++ b/src/wifi/wscript	Wed Feb 17 22:40:00 2016 +0100
@@ -72,6 +72,7 @@
         'model/wifi-radio-energy-model.cc',
         'model/wifi-tx-current-model.cc',
         'model/vht-capabilities.cc',
+        'model/erp-information.cc',
         'helper/wifi-radio-energy-model-helper.cc',
         'helper/vht-wifi-mac-helper.cc',
         'helper/ht-wifi-mac-helper.cc',
@@ -166,6 +167,7 @@
         'model/wifi-radio-energy-model.h',
         'model/wifi-tx-current-model.h',
         'model/vht-capabilities.h',
+        'model/erp-information.h',
         'helper/wifi-radio-energy-model-helper.h',
         'helper/vht-wifi-mac-helper.h',
         'helper/ht-wifi-mac-helper.h',