wifi: Add threshold-based preamble detection model
authorSébastien Deronne <sebastien.deronne@gmail.com>
Mon, 03 Dec 2018 21:18:05 +0100
changeset 13877 8ce4c7c7398c
parent 13876 04881484a542
child 13878 0cb5fc48c184
wifi: Add threshold-based preamble detection model
CHANGES.html
RELEASE_NOTES
src/mesh/test/dot11s/hwmp-proactive-regression-test-0-1.pcap
src/mesh/test/dot11s/hwmp-proactive-regression-test-1-1.pcap
src/mesh/test/dot11s/hwmp-proactive-regression-test-2-1.pcap
src/mesh/test/dot11s/hwmp-proactive-regression-test-3-1.pcap
src/mesh/test/dot11s/hwmp-proactive-regression-test-4-1.pcap
src/mesh/test/dot11s/hwmp-reactive-regression-test-0-1.pcap
src/mesh/test/dot11s/hwmp-reactive-regression-test-1-1.pcap
src/mesh/test/dot11s/hwmp-reactive-regression-test-2-1.pcap
src/mesh/test/dot11s/hwmp-reactive-regression-test-3-1.pcap
src/mesh/test/dot11s/hwmp-reactive-regression-test-4-1.pcap
src/mesh/test/dot11s/hwmp-reactive-regression-test-5-1.pcap
src/wifi/doc/source/wifi-design.rst
src/wifi/model/interference-helper.cc
src/wifi/model/preamble-detection-model.cc
src/wifi/model/preamble-detection-model.h
src/wifi/model/spectrum-wifi-phy.cc
src/wifi/model/threshold-preamble-detection-model.cc
src/wifi/model/threshold-preamble-detection-model.h
src/wifi/model/wifi-phy.cc
src/wifi/model/wifi-phy.h
src/wifi/model/yans-wifi-channel.cc
src/wifi/test/preamble-detection-test.cc
src/wifi/test/wifi-test.cc
src/wifi/wscript
--- a/CHANGES.html	Mon Dec 03 11:04:49 2018 +0100
+++ b/CHANGES.html	Mon Dec 03 21:18:05 2018 +0100
@@ -58,6 +58,7 @@
 </li>
 <li>A new attribute <b>WifiPhy::PostReceptionErrorModel</b> has been added to force specific packet drops.
 </li>
+<li>A new attribute <b>WifiPhy::PreambleDetectionModel</b> has been added to decide whether PHY preambles are successfully detected.
 </li>
 <li>New attributes <b>QosTxop::AddBaResponseTimeout</b> and <b>QosTxop::FailedAddBaTimeout</b> have been added to set the timeout to wait for an ADDBA response after the ACK to the ADDBA request is received and to set the timeout after a failed BA agreement, respectively.
 </li>
--- a/RELEASE_NOTES	Mon Dec 03 11:04:49 2018 +0100
+++ b/RELEASE_NOTES	Mon Dec 03 21:18:05 2018 +0100
@@ -23,6 +23,7 @@
 
 New user-visible features
 -------------------------
+- (wifi) Preamble detection can now be modelled
 
 Bugs fixed
 ----------
Binary file src/mesh/test/dot11s/hwmp-proactive-regression-test-0-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-proactive-regression-test-1-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-proactive-regression-test-2-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-proactive-regression-test-3-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-proactive-regression-test-4-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-reactive-regression-test-0-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-reactive-regression-test-1-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-reactive-regression-test-2-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-reactive-regression-test-3-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-reactive-regression-test-4-1.pcap has changed
Binary file src/mesh/test/dot11s/hwmp-reactive-regression-test-5-1.pcap has changed
--- a/src/wifi/doc/source/wifi-design.rst	Mon Dec 03 11:04:49 2018 +0100
+++ b/src/wifi/doc/source/wifi-design.rst	Mon Dec 03 21:18:05 2018 +0100
@@ -175,7 +175,6 @@
 * 802.11 PCF implementation currently assumes a DTIM interval equal to the beacon interval
 * Authentication and encryption are missing
 * Processing delays are not modeled
-* PLCP preamble reception is not modeled
 * PHY_RXSTART is not supported
 * The current implementation assumes that secondary channels are always higher than primary channels
 * Cases where RTS/CTS and ACK are transmitted using HT/VHT/HE formats are not supported
@@ -297,9 +296,9 @@
 and coding rate sensitivity" in section 18.3.10.6 CCA requirements. 
 This is analogous to the RxSensitivity attribute in ``YansWifiPhy``.
 CCA busy state is not raised in this model when this threshold is exceeded
-but instead RX state is immediately reached, since it is assumed that PLCP
-sync always succeeds in this model. Even if the PLCP header reception fails, the 
-channel state is still held in RX until YansWifiPhy::EndReceive().
+but instead RX state is immediately reachedif PHY preamble detection is successful.
+Even if the PHY header reception fails, the channel state is still held
+in RX until YansWifiPhy::EndReceive().
 
 In ns-3, the values of these attributes are -101 dBm for RxSensitivity
 and -62 dBm for CcaEdThreshold.  
@@ -311,10 +310,15 @@
 of the transmitter, Rx gain of the receiver, and any path loss propagation
 model in effect.
 
-The packet reception occurs in two stages.   First, an event is scheduled
-for when the PLCP header has been received. PLCP header is often transmitted
+The packet reception occurs in three stages. First, an event is scheduled
+for when PHY preamble has been detected. This decides whether the preamble
+can be detected, by calling a preamble detection model. In case there is no
+preamble detection model attached to the PHY, it assumes preamble is always detected.
+Currently, there is only a simple threshold-based preamble detection model in ns-3,
+called ``ThresholdPreambleDetectionModel``. If PHY preamble has been successfully detected,
+it schedules a second event for when PHY header has been received. PHY header is often transmitted
 at a lower modulation rate than is the payload.  The portion of the packet
-corresponding to the PLCP header is evaluated for probability of error 
+corresponding to the PHY header is evaluated for probability of error
 based on the observed SNR.  The InterferenceHelper object returns a value
 for "probability of error (PER)" for this header based on the SNR that has
 been tracked by the InterferenceHelper.  The ``YansWifiPhy`` then draws
--- a/src/wifi/model/interference-helper.cc	Mon Dec 03 11:04:49 2018 +0100
+++ b/src/wifi/model/interference-helper.cc	Mon Dec 03 21:18:05 2018 +0100
@@ -25,6 +25,7 @@
 #include "interference-helper.h"
 #include "wifi-phy.h"
 #include "error-rate-model.h"
+#include "wifi-utils.h"
 
 namespace ns3 {
 
@@ -229,26 +230,36 @@
   double noiseFloor = m_noiseFigure * Nt;
   double noise = noiseFloor + noiseInterference;
   double snr = signal / noise; //linear scale
-  NS_LOG_DEBUG ("bandwidth(MHz)=" << channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr(linear)=" << snr);
+  NS_LOG_DEBUG ("bandwidth(MHz)=" << channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr=" << RatioToDb(snr) << "dB");
   return snr;
 }
 
 double
 InterferenceHelper::CalculateNoiseInterferenceW (Ptr<Event> event, NiChanges *ni) const
 {
-  double noiseInterference = m_firstPower;
+  double noiseInterferenceW = m_firstPower;
   auto it = m_niChanges.find (event->GetStartTime ());
-  for (; it != m_niChanges.end () && it->second.GetEvent () != event; ++it)
+  for (; it != m_niChanges.end (); ++it)
     {
-      noiseInterference = it->second.GetPower ();
+      if (it->second.GetEvent () == event)
+        {
+          continue;
+        }
+      if (it->first > Simulator::Now ())
+        {
+          break;
+        }
+      noiseInterferenceW = it->second.GetPower () - event->GetRxPowerW ();
     }
+  it = m_niChanges.find (event->GetStartTime ());
+  for (; it != m_niChanges.end () && it->second.GetEvent () != event; ++it);
   ni->emplace (event->GetStartTime (), NiChange (0, event));
   while (++it != m_niChanges.end () && it->second.GetEvent () != event)
     {
       ni->insert (*it);
     }
   ni->emplace (event->GetEndTime (), NiChange (0, event));
-  return noiseInterference;
+  return noiseInterferenceW;
 }
 
 double
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/preamble-detection-model.cc	Mon Dec 03 21:18:05 2018 +0100
@@ -0,0 +1,36 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2018 University of Washington
+ *
+ * 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 <[email protected]>
+ */
+
+#include "preamble-detection-model.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (PreambleDetectionModel);
+
+TypeId PreambleDetectionModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::PreambleDetectionModel")
+    .SetParent<Object> ()
+    .SetGroupName ("Wifi")
+  ;
+  return tid;
+}
+
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/preamble-detection-model.h	Mon Dec 03 21:18:05 2018 +0100
@@ -0,0 +1,58 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2018 University of Washington
+ *
+ * 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 <[email protected]>
+ */
+
+#ifndef PREAMBLE_DETECTION_MODEL_H
+#define PREAMBLE_DETECTION_MODEL_H
+
+#include "ns3/object.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup wifi
+ * \brief the interface for Wifi's preamble detection models
+ *
+ */
+class PreambleDetectionModel : public Object
+{
+public:
+  /**
+   * \brief Get the type ID.
+   * \return the object TypeId
+   */
+  static TypeId GetTypeId (void);
+
+  /**
+   * A pure virtual method that must be implemented in the subclass.
+   * This method returns whether the preamble detection was successful.
+   *
+   * \param snr the SNR of the received signal.
+   * \param channelWidth the channel width of the received signal in MHz.
+   *
+   * \return true if the preamble has been detected,
+   *         false otherwise
+   */
+  virtual bool IsPreambleDetected (double snr, double channelWidth) const = 0;
+};
+
+} //namespace ns3
+
+#endif /* PREAMBLE_DETECTION_MODEL_H */
+
--- a/src/wifi/model/spectrum-wifi-phy.cc	Mon Dec 03 11:04:49 2018 +0100
+++ b/src/wifi/model/spectrum-wifi-phy.cc	Mon Dec 03 21:18:05 2018 +0100
@@ -240,7 +240,7 @@
 
   NS_LOG_INFO ("Received Wi-Fi signal");
   Ptr<Packet> packet = wifiRxParams->packet->Copy ();
-  StartReceivePreambleAndHeader (packet, rxPowerW, rxDuration);
+  StartReceivePreamble (packet, rxPowerW, rxDuration);
 }
 
 Ptr<AntennaModel>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/threshold-preamble-detection-model.cc	Mon Dec 03 21:18:05 2018 +0100
@@ -0,0 +1,65 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2018 University of Washington
+ *
+ * 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 <[email protected]>
+ */
+
+#include "ns3/log.h"
+#include "ns3/double.h"
+#include "threshold-preamble-detection-model.h"
+#include "wifi-utils.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("ThresholdPreambleDetectionModel");
+
+NS_OBJECT_ENSURE_REGISTERED (ThresholdPreambleDetectionModel);
+
+TypeId
+ThresholdPreambleDetectionModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ThresholdPreambleDetectionModel")
+    .SetParent<PreambleDetectionModel> ()
+    .SetGroupName ("Wifi")
+    .AddConstructor<ThresholdPreambleDetectionModel> ()
+    .AddAttribute ("Threshold",
+                   "Preamble is successfully detection if the SNR is at or above this value (expressed in dB).",
+                   DoubleValue (2),
+                   MakeDoubleAccessor (&ThresholdPreambleDetectionModel::m_threshold),
+                   MakeDoubleChecker<double> ())
+  ;
+  return tid;
+}
+
+ThresholdPreambleDetectionModel::ThresholdPreambleDetectionModel ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+ThresholdPreambleDetectionModel::~ThresholdPreambleDetectionModel ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+bool
+ThresholdPreambleDetectionModel::IsPreambleDetected (double snr, double channelWidth) const
+{
+  NS_LOG_FUNCTION (this);
+  return (RatioToDb (snr) >= m_threshold);
+}
+
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/model/threshold-preamble-detection-model.h	Mon Dec 03 21:18:05 2018 +0100
@@ -0,0 +1,63 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2018 University of Washington
+ *
+ * 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 <[email protected]>
+ */
+
+#ifndef THRESHOLD_PREAMBLE_DETECTION_MODEL_H
+#define THRESHOLD_PREAMBLE_DETECTION_MODEL_H
+
+#include "preamble-detection-model.h"
+
+namespace ns3 {
+/**
+ * \ingroup wifi
+ *
+ * A threshold-based model for detecting PHY preamble.
+ * This model assumes that a preamble is successfully detected if SNR is at or above a given threshold. By default, this threshold is set to 2 dB.
+ */
+class ThresholdPreambleDetectionModel : public PreambleDetectionModel
+{
+public:
+  /**
+   * \brief Get the type ID.
+   * \return the object TypeId
+   */
+  static TypeId GetTypeId (void);
+
+  ThresholdPreambleDetectionModel ();
+  ~ThresholdPreambleDetectionModel ();
+
+  /**
+   * This method returns whether the preamble detection was successful.
+   *
+   * \param snr the SNR ratio (not dB) of the received signal.
+   * \param channelWidth the channel width of the received signal in MHz.
+   *
+   * \return true if the preamble has been detected,
+   *         false otherwise
+   */
+  bool IsPreambleDetected (double snr, double channelWidth) const;
+
+
+private:
+  double m_threshold; ///< SNR threshold in dB used to decide whether a preamble is successfully received
+};
+
+} //namespace ns3
+
+#endif /* THRESHOLD_PREAMBLE_DETECTION_MODEL_H */
--- a/src/wifi/model/wifi-phy.cc	Mon Dec 03 11:04:49 2018 +0100
+++ b/src/wifi/model/wifi-phy.cc	Mon Dec 03 21:18:05 2018 +0100
@@ -30,6 +30,7 @@
 #include "ampdu-tag.h"
 #include "wifi-utils.h"
 #include "frame-capture-model.h"
+#include "preamble-detection-model.h"
 #include "wifi-radio-energy-model.h"
 #include "error-rate-model.h"
 #include "wifi-net-device.h"
@@ -308,6 +309,11 @@
                    PointerValue (),
                    MakePointerAccessor (&WifiPhy::m_frameCaptureModel),
                    MakePointerChecker <FrameCaptureModel> ())
+    .AddAttribute ("PreambleDetectionModel",
+                   "Ptr to an object that implements the preamble detection model",
+                   PointerValue (),
+                   MakePointerAccessor (&WifiPhy::m_preambleDetectionModel),
+                   MakePointerChecker <PreambleDetectionModel> ())
     .AddAttribute ("PostReceptionErrorModel",
                    "An optional packet error model can be added to the receive "
                    "packet process after any propagation-based (SNR-based) error "
@@ -372,6 +378,7 @@
     m_rxMpduReferenceNumber (0xffffffff),
     m_endRxEvent (),
     m_endPlcpRxEvent (),
+    m_endPreambleDetectionEvent (),
     m_standard (WIFI_PHY_STANDARD_UNSPECIFIED),
     m_isConstructed (false),
     m_channelCenterFrequency (0),
@@ -401,6 +408,9 @@
 WifiPhy::DoDispose (void)
 {
   NS_LOG_FUNCTION (this);
+  m_endRxEvent.Cancel ();
+  m_endPlcpRxEvent.Cancel ();
+  m_endPreambleDetectionEvent.Cancel ();
   m_device = 0;
   m_mobility = 0;
   m_state = 0;
@@ -763,6 +773,12 @@
 }
 
 void
+WifiPhy::SetPreambleDetectionModel (const Ptr<PreambleDetectionModel> model)
+{
+  m_preambleDetectionModel = model;
+}
+
+void
 WifiPhy::SetWifiRadioEnergyModel (const Ptr<WifiRadioEnergyModel> wifiRadioEnergyModel)
 {
   m_wifiRadioEnergyModel = wifiRadioEnergyModel;
@@ -1506,6 +1522,7 @@
       NS_LOG_DEBUG ("drop packet because of channel switching while reception");
       m_endPlcpRxEvent.Cancel ();
       m_endRxEvent.Cancel ();
+      m_endPreambleDetectionEvent.Cancel ();
       goto switchChannel;
       break;
     case WifiPhyState::TX:
@@ -1514,6 +1531,11 @@
       break;
     case WifiPhyState::CCA_BUSY:
     case WifiPhyState::IDLE:
+      if (m_endPreambleDetectionEvent.IsRunning ())
+      {
+        m_endPreambleDetectionEvent.Cancel ();
+        m_endRxEvent.Cancel ();
+      }
       goto switchChannel;
       break;
     case WifiPhyState::SLEEP:
@@ -1558,6 +1580,7 @@
       NS_LOG_DEBUG ("drop packet because of channel/frequency switching while reception");
       m_endPlcpRxEvent.Cancel ();
       m_endRxEvent.Cancel ();
+      m_endPreambleDetectionEvent.Cancel ();
       goto switchFrequency;
       break;
     case WifiPhyState::TX:
@@ -1566,6 +1589,11 @@
       break;
     case WifiPhyState::CCA_BUSY:
     case WifiPhyState::IDLE:
+      if (m_endPreambleDetectionEvent.IsRunning ())
+      {
+        m_endPreambleDetectionEvent.Cancel ();
+        m_endRxEvent.Cancel ();
+      }
       goto switchFrequency;
       break;
     case WifiPhyState::SLEEP:
@@ -1629,22 +1657,10 @@
 WifiPhy::SetOffMode (void)
 {
   NS_LOG_FUNCTION (this);
-  switch (m_state->GetState ())
-    {
-    case WifiPhyState::RX:
-      m_endPlcpRxEvent.Cancel ();
-      m_endRxEvent.Cancel ();
-    case WifiPhyState::TX:
-    case WifiPhyState::SWITCHING:
-    case WifiPhyState::CCA_BUSY:
-    case WifiPhyState::IDLE:
-    case WifiPhyState::SLEEP:
-      m_state->SwitchToOff ();
-      break;
-    default:
-      NS_ASSERT (false);
-      break;
-    }
+  m_endPlcpRxEvent.Cancel ();
+  m_endRxEvent.Cancel ();
+  m_endPreambleDetectionEvent.Cancel ();
+  m_state->SwitchToOff ();
 }
 
 void
@@ -1727,6 +1743,12 @@
 }
 
 Time
+WifiPhy::GetPreambleDetectionDuration (void)
+{
+  return MicroSeconds (4);
+}
+
+Time
 WifiPhy::GetPlcpTrainingSymbolDuration (WifiTxVector txVector)
 {
   uint8_t Ndltf, Neltf;
@@ -2389,12 +2411,23 @@
   Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, GetFrequency (), mpdutype, 1);
   NS_ASSERT (txDuration.IsStrictlyPositive ());
 
-  if (m_state->IsStateRx ())
+  if (m_endPreambleDetectionEvent.IsRunning ())
+    {
+      m_endPreambleDetectionEvent.Cancel ();
+    }
+  if (m_endPlcpRxEvent.IsRunning ())
     {
       m_endPlcpRxEvent.Cancel ();
+    }
+  if (m_endRxEvent.IsRunning ())
+    {
       m_endRxEvent.Cancel ();
+    }
+  if (m_state->IsStateRx ())
+    {
       m_interference.NotifyRxEnd ();
     }
+
   NotifyTxBegin (packet);
   if ((mpdutype == MPDU_IN_AGGREGATE) && (txVector.GetPreambleType () != WIFI_PREAMBLE_NONE))
     {
@@ -2427,7 +2460,39 @@
 }
 
 void
-WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Time rxDuration)
+WifiPhy::StartReceiveHeader (Ptr<Packet> packet, WifiTxVector txVector, MpduType mpdutype, Ptr<Event> event, Time rxDuration)
+{
+  NS_LOG_FUNCTION (this << packet << txVector.GetMode () << txVector.GetPreambleType () << +mpdutype);
+  NS_ASSERT (!IsStateRx ());
+  NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
+
+  InterferenceHelper::SnrPer snrPer = m_interference.CalculatePlcpHeaderSnrPer (event);
+  double snr = snrPer.snr;
+  NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per);
+
+  if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (snr, m_channelWidth)))
+  {
+    m_state->SwitchToRx (rxDuration);
+    NotifyRxBegin (packet);
+
+    Time remainingPreambleHeaderDuration = CalculatePlcpPreambleAndHeaderDuration (txVector) - GetPreambleDetectionDuration ();
+    m_endPlcpRxEvent = Simulator::Schedule (remainingPreambleHeaderDuration, &WifiPhy::StartReceivePacket, this,
+                                            packet, txVector, mpdutype, event);
+
+    NS_ASSERT (m_endRxEvent.IsExpired ());
+    m_endRxEvent = Simulator::Schedule (rxDuration, &WifiPhy::EndReceive, this,
+                                        packet, txVector.GetPreambleType (), mpdutype, event);
+  }
+  else
+  {
+    NS_LOG_DEBUG ("Packet reception could not be started because PHY preamble detection failed");
+    m_plcpSuccess = false;
+    m_interference.NotifyRxEnd ();
+  }
+}
+
+void
+WifiPhy::StartReceivePreamble (Ptr<Packet> packet, double rxPowerW, Time rxDuration)
 {
   WifiPhyTag tag;
   bool found = packet->RemovePacketTag (tag);
@@ -2456,8 +2521,7 @@
 
   if (tag.GetFrameComplete () == 0)
     {
-      NS_LOG_DEBUG ("drop packet because of incomplete frame");
-      NotifyRxDrop (packet);
+      NS_LOG_DEBUG ("Packet reception stopped because transmitter has been switched off");
       m_plcpSuccess = false;
       return;
     }
@@ -2471,8 +2535,7 @@
   Time endRx = Simulator::Now () + rxDuration;
   if (txVector.GetNss () > GetMaxSupportedRxSpatialStreams ())
     {
-      NS_LOG_DEBUG ("drop packet because not enough RX antennas");
-      NotifyRxDrop (packet);
+      NS_LOG_DEBUG ("Packet reception could not be started because not enough RX antennas");
       m_plcpSuccess = false;
       if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
         {
@@ -2585,8 +2648,6 @@
   InterferenceHelper::SnrPer snrPer;
   snrPer = m_interference.CalculatePlcpHeaderSnrPer (event);
 
-  NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per);
-
   if (m_random->GetValue () > snrPer.per) //plcp reception succeeded
     {
       if (IsModeSupported (txMode) || IsMcsSupported (txMode))
@@ -2603,7 +2664,7 @@
     }
   else //plcp reception failed
     {
-      NS_LOG_DEBUG ("drop packet because plcp preamble/header reception failed");
+      NS_LOG_DEBUG ("drop packet because PHY header reception failed");
       NotifyRxDrop (packet);
       m_plcpSuccess = false;
     }
@@ -3679,6 +3740,10 @@
 WifiPhy::AbortCurrentReception ()
 {
   NS_LOG_FUNCTION (this);
+  if (m_endPreambleDetectionEvent.IsRunning ())
+    {
+      m_endPreambleDetectionEvent.Cancel ();
+    }
   if (m_endPlcpRxEvent.IsRunning ())
     {
       m_endPlcpRxEvent.Cancel ();
@@ -3741,22 +3806,31 @@
 
   NS_LOG_DEBUG ("sync to signal (power=" << rxPowerW << "W)");
   m_currentEvent = event;
-  m_state->SwitchToRx (rxDuration);
-  NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
-  NotifyRxBegin (packet);
-  m_interference.NotifyRxStart ();
-
-  if (preamble != WIFI_PREAMBLE_NONE)
+  m_interference.NotifyRxStart (); //We need to notify it now so that it starts recording events
+  if (preamble == WIFI_PREAMBLE_NONE)
+    {
+      m_state->SwitchToRx (rxDuration);
+      NotifyRxBegin (packet);
+      m_interference.NotifyRxStart ();
+
+      NS_ASSERT (m_endRxEvent.IsExpired ());
+      m_endRxEvent = Simulator::Schedule (rxDuration, &WifiPhy::EndReceive, this,
+                                          packet, txVector.GetPreambleType (), mpdutype, event);
+    }
+  else
     {
-      NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
-      Time preambleAndHeaderDuration = CalculatePlcpPreambleAndHeaderDuration (txVector);
-      m_endPlcpRxEvent = Simulator::Schedule (preambleAndHeaderDuration, &WifiPhy::StartReceivePacket, this,
-                                              packet, txVector, mpdutype, event);
+      if (!m_endPreambleDetectionEvent.IsRunning ())
+        {
+          Time startOfPreambleDuration = GetPreambleDetectionDuration ();
+          Time remainingRxDuration = rxDuration - startOfPreambleDuration;
+          m_endPreambleDetectionEvent = Simulator::Schedule (startOfPreambleDuration, &WifiPhy::StartReceiveHeader, this,
+                                                             packet, txVector, mpdutype, event, remainingRxDuration);
+        }
+      else
+        {
+          NS_LOG_DEBUG ("Ignore packet because RX is already decoding preamble");
+        }
     }
-
-  NS_ASSERT (m_endRxEvent.IsExpired ());
-  m_endRxEvent = Simulator::Schedule (rxDuration, &WifiPhy::EndReceive, this,
-                                      packet, preamble, mpdutype, event);
 }
 
 int64_t
--- a/src/wifi/model/wifi-phy.h	Mon Dec 03 11:04:49 2018 +0100
+++ b/src/wifi/model/wifi-phy.h	Mon Dec 03 21:18:05 2018 +0100
@@ -41,6 +41,7 @@
 class MobilityModel;
 class WifiPhyStateHelper;
 class FrameCaptureModel;
+class PreambleDetectionModel;
 class WifiRadioEnergyModel;
 class UniformRandomVariable;
 
@@ -114,15 +115,29 @@
   void SetCapabilitiesChangedCallback (Callback<void> callback);
 
   /**
-   * Starting receiving the plcp of a packet (i.e. the first bit of the preamble has arrived).
+   * Starting receiving the PHY preamble of a packet (i.e. the first bit of the preamble has arrived).
    *
    * \param packet the arriving packet
    * \param rxPowerW the receive power in W
    * \param rxDuration the duration needed for the reception of the packet
    */
-  void StartReceivePreambleAndHeader (Ptr<Packet> packet,
-                                      double rxPowerW,
-                                      Time rxDuration);
+  void StartReceivePreamble (Ptr<Packet> packet,
+                             double rxPowerW,
+                             Time rxDuration);
+
+  /**
+   * Starting receiving the PHY header of a packet (i.e. after the end of receiving the preamble).
+   *
+   * \param packet the arriving packet
+   * \param txVector the TXVECTOR of the arriving packet
+   * \param mpdutype the type of the MPDU as defined in WifiPhy::MpduType.
+   * \param event the corresponding event of the first time the packet arrives
+   */
+  void StartReceiveHeader (Ptr<Packet> packet,
+                           WifiTxVector txVector,
+                           MpduType mpdutype,
+                           Ptr<Event> event,
+                           Time rxDuration);
 
   /**
    * Starting receiving the payload of a packet (i.e. the first bit of the packet has arrived).
@@ -253,6 +268,12 @@
   static Time CalculatePlcpPreambleAndHeaderDuration (WifiTxVector txVector);
 
   /**
+   *
+   * \return the preamble detection duration, which is the time correletion needs to detect the start of an incoming frame.
+   */
+  Time GetPreambleDetectionDuration (void);
+
+  /**
    * \param txVector the transmission parameters used for this packet
    *
    * \return the training symbol duration
@@ -1447,6 +1468,12 @@
    */
   void SetFrameCaptureModel (const Ptr<FrameCaptureModel> frameCaptureModel);
   /**
+   * Sets the preamble detection model.
+   *
+   * \param preambleDetectionModel the preamble detection model
+   */
+  void SetPreambleDetectionModel (const Ptr<PreambleDetectionModel> preambleDetectionModel);
+  /**
    * Sets the wifi radio energy model.
    *
    * \param wifiRadioEnergyModel the wifi radio energy model
@@ -1524,8 +1551,9 @@
   uint32_t m_txMpduReferenceNumber;    //!< A-MPDU reference number to identify all transmitted subframes belonging to the same received A-MPDU
   uint32_t m_rxMpduReferenceNumber;    //!< A-MPDU reference number to identify all received subframes belonging to the same received A-MPDU
 
-  EventId m_endRxEvent;                //!< the end reeive event
-  EventId m_endPlcpRxEvent;            //!< the end PLCP receive event
+  EventId m_endRxEvent;                //!< the end of receive event
+  EventId m_endPlcpRxEvent;            //!< the end of PLCP receive event
+  EventId m_endPreambleDetectionEvent;   //!< the end of preamble detection event
 
 private:
   /**
@@ -1807,6 +1835,7 @@
 
   Ptr<Event> m_currentEvent; //!< Hold the current event
   Ptr<FrameCaptureModel> m_frameCaptureModel; //!< Frame capture model
+  Ptr<PreambleDetectionModel> m_preambleDetectionModel; //!< Preamble detection model
   Ptr<WifiRadioEnergyModel> m_wifiRadioEnergyModel; //!< Wifi radio energy model
   Ptr<ErrorModel> m_postReceptionErrorModel; //!< Error model for receive packet events
 
--- a/src/wifi/model/yans-wifi-channel.cc	Mon Dec 03 11:04:49 2018 +0100
+++ b/src/wifi/model/yans-wifi-channel.cc	Mon Dec 03 21:18:05 2018 +0100
@@ -132,7 +132,7 @@
       NS_LOG_INFO ("Received signal too weak to process: " << rxPowerDbm << " dBm");
       return;
     }
-  phy->StartReceivePreambleAndHeader (packet, DbmToW (rxPowerDbm + phy->GetRxGain ()), duration);
+  phy->StartReceivePreamble (packet, DbmToW (rxPowerDbm + phy->GetRxGain ()), duration);
 }
 
 std::size_t
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wifi/test/preamble-detection-test.cc	Mon Dec 03 21:18:05 2018 +0100
@@ -0,0 +1,254 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2018 University of Washington
+ *
+ * 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 <[email protected]>
+ */
+
+#include "ns3/log.h"
+#include "ns3/test.h"
+#include "ns3/pointer.h"
+#include "ns3/spectrum-wifi-helper.h"
+#include "ns3/wifi-spectrum-value-helper.h"
+#include "ns3/spectrum-wifi-phy.h"
+#include "ns3/nist-error-rate-model.h"
+#include "ns3/wifi-mac-header.h"
+#include "ns3/wifi-mac-trailer.h"
+#include "ns3/wifi-phy-tag.h"
+#include "ns3/wifi-spectrum-signal-parameters.h"
+#include "ns3/wifi-utils.h"
+#include "ns3/threshold-preamble-detection-model.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TestThresholdPreambleDetectionWithoutFrameCapture");
+
+static const uint8_t CHANNEL_NUMBER = 36;
+static const uint32_t FREQUENCY = 5180; // MHz
+static const uint16_t CHANNEL_WIDTH = 20; // MHz
+static const uint16_t GUARD_WIDTH = CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
+
+/**
+ * \ingroup wifi-test
+ * \ingroup tests
+ *
+ * \brief Wifi Preamble Detection Test
+ */
+class TestThresholdPreambleDetectionWithoutFrameCapture : public TestCase
+{
+public:
+  TestThresholdPreambleDetectionWithoutFrameCapture ();
+  virtual ~TestThresholdPreambleDetectionWithoutFrameCapture ();
+
+protected:
+  virtual void DoSetup (void);
+  Ptr<SpectrumWifiPhy> m_phy; ///< Phy
+  /**
+   * Send packet function
+   * \param txPowerDbm the transmit power in dBm
+   */
+  void SendPacket (double txPowerDbm);
+  /**
+   * Spectrum wifi receive success function
+   * \param p the packet
+   * \param snr the SNR
+   * \param txVector the transmit vector
+   */
+  void SpectrumWifiPhyRxSuccess (Ptr<Packet> p, double snr, WifiTxVector txVector);
+  /**
+   * Spectrum wifi receive failure function
+   */
+  void SpectrumWifiPhyRxFailure (void);
+  uint32_t m_countRxSuccess; ///< count RX success
+  uint32_t m_countRxFailure; ///< count RX failure
+
+private:
+  virtual void DoRun (void);
+
+  /**
+   * Check the PHY state
+   * \param expectedState the expected PHY state
+   */
+  void CheckPhyState (WifiPhyState expectedState);
+  /**
+   * Check the number of received packets
+   * \param expectedSuccessCount the number of successfully received packets
+   * \param expectedFailureCount the number of unsuccessfully received packets
+   */
+  void CheckRxPacketCount (uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
+};
+
+TestThresholdPreambleDetectionWithoutFrameCapture::TestThresholdPreambleDetectionWithoutFrameCapture ()
+  : TestCase ("Threshold preamble detection model test when no frame capture model is applied"),
+    m_countRxSuccess (0),
+    m_countRxFailure (0)
+{
+}
+
+void
+TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket (double txPowerDbm)
+{
+  WifiTxVector txVector = WifiTxVector (WifiPhy::GetHeMcs11 (), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false, false);
+  MpduType mpdutype = NORMAL_MPDU;
+
+  Ptr<Packet> pkt = Create<Packet> (1000);
+  WifiMacHeader hdr;
+  WifiMacTrailer trailer;
+
+  hdr.SetType (WIFI_MAC_QOSDATA);
+  hdr.SetQosTid (0);
+  uint32_t size = pkt->GetSize () + hdr.GetSize () + trailer.GetSerializedSize ();
+  Time txDuration = m_phy->CalculateTxDuration (size, txVector, m_phy->GetFrequency (), mpdutype, 0);
+  hdr.SetDuration (txDuration);
+
+  pkt->AddHeader (hdr);
+  pkt->AddTrailer (trailer);
+  WifiPhyTag tag (txVector, mpdutype, 1);
+  pkt->AddPacketTag (tag);
+  Ptr<SpectrumValue> txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (txPowerDbm), GUARD_WIDTH);
+  Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
+  txParams->psd = txPowerSpectrum;
+  txParams->txPhy = 0;
+  txParams->duration = txDuration;
+  txParams->packet = pkt;
+
+  m_phy->StartRx (txParams);
+}
+
+void
+TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState (WifiPhyState expectedState)
+{
+  WifiPhyState currentState;
+  PointerValue ptr;
+  m_phy->GetAttribute ("State", ptr);
+  Ptr <WifiPhyStateHelper> state = DynamicCast <WifiPhyStateHelper> (ptr.Get<WifiPhyStateHelper> ());
+  currentState = state->GetState ();
+  NS_TEST_ASSERT_MSG_EQ (currentState, expectedState, "PHY State " << currentState << " does not match expected state " << expectedState << " at " << Simulator::Now ());
+}
+
+void
+TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount (uint32_t expectedSuccessCount, uint32_t expectedFailureCount)
+{
+  NS_TEST_ASSERT_MSG_EQ (m_countRxSuccess, expectedSuccessCount, "Didn't receive right number of successful packets");
+  NS_TEST_ASSERT_MSG_EQ (m_countRxFailure, expectedFailureCount, "Didn't receive right number of unsuccessful packets");
+}
+
+void
+TestThresholdPreambleDetectionWithoutFrameCapture::SpectrumWifiPhyRxSuccess (Ptr<Packet> p, double snr, WifiTxVector txVector)
+{
+  NS_LOG_FUNCTION (this << p << snr << txVector);
+  m_countRxSuccess++;
+}
+
+void
+TestThresholdPreambleDetectionWithoutFrameCapture::SpectrumWifiPhyRxFailure (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_countRxFailure++;
+}
+
+TestThresholdPreambleDetectionWithoutFrameCapture::~TestThresholdPreambleDetectionWithoutFrameCapture ()
+{
+}
+
+void
+TestThresholdPreambleDetectionWithoutFrameCapture::DoSetup (void)
+{
+  m_phy = CreateObject<SpectrumWifiPhy> ();
+  m_phy->ConfigureStandard (WIFI_PHY_STANDARD_80211ax_5GHZ);
+  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
+  m_phy->SetErrorRateModel (error);
+  m_phy->SetChannelNumber (CHANNEL_NUMBER);
+  m_phy->SetFrequency (FREQUENCY);
+  m_phy->SetReceiveOkCallback (MakeCallback (&TestThresholdPreambleDetectionWithoutFrameCapture::SpectrumWifiPhyRxSuccess, this));
+  m_phy->SetReceiveErrorCallback (MakeCallback (&TestThresholdPreambleDetectionWithoutFrameCapture::SpectrumWifiPhyRxFailure, this));
+
+  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel> ();
+  m_phy->SetPreambleDetectionModel (preambleDetectionModel);
+}
+
+// Test that the expected number of packet receptions occur.
+void
+TestThresholdPreambleDetectionWithoutFrameCapture::DoRun (void)
+{
+  double txPowerDbm = -30;
+
+  //CASE 1: send one packet and check PHY state: packet reception should succeed
+
+  Simulator::Schedule (Seconds (1.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
+  // At 4us, STA PHY STATE should be IDLE
+  Simulator::Schedule (Seconds (1.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
+  // At 5us, STA PHY STATE should be RX
+  Simulator::Schedule (Seconds (1.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::RX);
+  // Packet should have been successfully received
+  Simulator::Schedule (Seconds (1.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 0);
+
+  //CASE 2: send two packets with same power within the 4us window and check PHY state: PHY preamble detection should fail
+
+  Simulator::Schedule (Seconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
+  Simulator::Schedule (Seconds (2.0) + MicroSeconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
+  Simulator::Schedule (Seconds (2.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
+  Simulator::Schedule (Seconds (2.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
+  // No more packet should have been successfully received, and since preamble detection did not pass the packet should not have been counted as a failure
+  Simulator::Schedule (Seconds (2.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 0);
+
+  //CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY state: PHY preamble detection should succeed and packet reception should fail
+
+  Simulator::Schedule (Seconds (3.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
+  Simulator::Schedule (Seconds (3.0) + MicroSeconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm - 3);
+  Simulator::Schedule (Seconds (3.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
+  Simulator::Schedule (Seconds (3.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::RX);
+  // In this case, the first packet should be marked as a failure
+  Simulator::Schedule (Seconds (3.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 1);
+
+  //CASE 4: send two packets with second one 3 dB higher within the 4us window and check PHY state: PHY preamble detection should fail and no packets should enter the reception stage
+  Simulator::Schedule (Seconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
+  Simulator::Schedule (Seconds (4.0) + MicroSeconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm + 3);
+  Simulator::Schedule (Seconds (4.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
+  Simulator::Schedule (Seconds (4.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
+  Simulator::Schedule (Seconds (4.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 1);
+
+  //CASE 5: idem but send the second packet after the 4us window: PHY preamble detection should succeed and packet reception should fail
+
+  Simulator::Schedule (Seconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
+  Simulator::Schedule (Seconds (5.0) + MicroSeconds (6.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm + 3);
+  Simulator::Schedule (Seconds (5.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
+  Simulator::Schedule (Seconds (5.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::RX);
+  Simulator::Schedule (Seconds (5.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 2);
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+}
+
+/**
+ * \ingroup wifi-test
+ * \ingroup tests
+ *
+ * \brief Preamble Detection Test Suite
+ */
+class PreambleDetectionTestSuite : public TestSuite
+{
+public:
+  PreambleDetectionTestSuite ();
+};
+
+PreambleDetectionTestSuite::PreambleDetectionTestSuite ()
+  : TestSuite ("wifi-preamble-detection", UNIT)
+{
+  AddTestCase (new TestThresholdPreambleDetectionWithoutFrameCapture, TestCase::QUICK);
+}
+
+static PreambleDetectionTestSuite preambleDetectionTestSuite; ///< the test suite
--- a/src/wifi/test/wifi-test.cc	Mon Dec 03 11:04:49 2018 +0100
+++ b/src/wifi/test/wifi-test.cc	Mon Dec 03 21:18:05 2018 +0100
@@ -1025,7 +1025,6 @@
   }
 
   Simulator::Destroy ();
-
 }
 
 //-----------------------------------------------------------------------------
@@ -1656,6 +1655,9 @@
 StaWifiMacScanningTestCase::DoRun (void)
 {
   {
+    RngSeedManager::SetSeed (1);
+    RngSeedManager::SetRun (1);
+  
     NodeContainer nodes = Setup (false, false);
     Ptr<Node> nearestAp = nodes.Get (2);
     Mac48Address nearestApAddr = DynamicCast<WifiNetDevice> (nearestAp->GetDevice (0))->GetMac ()->GetAddress ();
@@ -1670,6 +1672,9 @@
   }
   m_associatedApBssid = Mac48Address ();
   {
+    RngSeedManager::SetSeed (1);
+    RngSeedManager::SetRun (1);
+
     NodeContainer nodes = Setup (true, true);
     Ptr<Node> nearestAp = nodes.Get (2);
     Mac48Address nearestApAddr = DynamicCast<WifiNetDevice> (nearestAp->GetDevice (0))->GetMac ()->GetAddress ();
@@ -1682,6 +1687,9 @@
   }
   m_associatedApBssid = Mac48Address ();
   {
+    RngSeedManager::SetSeed (1);
+    RngSeedManager::SetRun (1);
+
     NodeContainer nodes = Setup (true, false);
     Ptr<Node> nearestAp = nodes.Get (2);
     Mac48Address secondNearestApAddr = DynamicCast<WifiNetDevice> (nodes.Get (1)->GetDevice (0))->GetMac ()->GetAddress ();
--- a/src/wifi/wscript	Mon Dec 03 11:04:49 2018 +0100
+++ b/src/wifi/wscript	Mon Dec 03 21:18:05 2018 +0100
@@ -85,6 +85,8 @@
         'model/he-capabilities.cc',
         'model/frame-capture-model.cc',
         'model/simple-frame-capture-model.cc',
+        'model/preamble-detection-model.cc',
+        'model/threshold-preamble-detection-model.cc',
         'model/he-operation.cc',
         'model/he-configuration.cc',
         'model/extended-capabilities.cc',
@@ -112,6 +114,7 @@
         'test/wifi-error-rate-models-test.cc',
         'test/wifi-transmit-mask-test.cc',
         'test/wifi-phy-thresholds-test.cc',
+        'test/preamble-detection-test.cc',
         ]
 
     headers = bld(features='ns3header')
@@ -200,6 +203,8 @@
         'model/he-capabilities.h',
         'model/frame-capture-model.h',
         'model/simple-frame-capture-model.h',
+        'model/preamble-detection-model.h',
+        'model/threshold-preamble-detection-model.h',
         'model/qos-blocked-destinations.h',
         'model/he-operation.h',
         'model/he-configuration.h',