Bug 2066 [wifi] - A-MPDU reception should check for successful preamble
authorSébastien Deronne <sebastien.deronne@gmail.com>
Sun, 03 May 2015 16:06:01 +0200
changeset 11348 ded786322135
parent 11347 3f8d3d686167
child 11349 adf2fc12ec15
Bug 2066 [wifi] - A-MPDU reception should check for successful preamble
src/wifi/model/interference-helper.cc
src/wifi/model/interference-helper.h
src/wifi/model/wifi-phy.cc
src/wifi/model/wifi-phy.h
src/wifi/model/yans-wifi-channel.cc
src/wifi/model/yans-wifi-phy.cc
src/wifi/model/yans-wifi-phy.h
--- a/src/wifi/model/interference-helper.cc	Sat May 02 22:21:58 2015 +0200
+++ b/src/wifi/model/interference-helper.cc	Sun May 03 16:06:01 2015 +0200
@@ -267,20 +267,13 @@
 }
 
 double
-InterferenceHelper::CalculatePer (Ptr<const InterferenceHelper::Event> event, NiChanges *ni) const
+InterferenceHelper::CalculatePlcpPayloadPer (Ptr<const InterferenceHelper::Event> event, NiChanges *ni) const
 {
   double psr = 1.0; /* Packet Success Rate */
   NiChanges::iterator j = ni->begin ();
   Time previous = (*j).GetTime ();
   WifiMode payloadMode = event->GetPayloadMode ();
   WifiPreamble preamble = event->GetPreambleType ();
- WifiMode MfHeaderMode ;
- if (preamble==WIFI_PREAMBLE_HT_MF)
-   {
-    MfHeaderMode = WifiPhy::GetMFPlcpHeaderMode (payloadMode, preamble); //return L-SIG mode
-
-   }
-  WifiMode headerMode = WifiPhy::GetPlcpHeaderMode (payloadMode, preamble);
   Time plcpHeaderStart = (*j).GetTime () + WifiPhy::GetPlcpPreambleDuration (payloadMode, preamble); //packet start time+ preamble
   Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (payloadMode, preamble);//packet start time+ preamble+L SIG
   Time plcpHtTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble);//packet start time+ preamble+L SIG+HT SIG
@@ -309,74 +302,143 @@
             { 
                //Case 2ai and 2aii: All formats
                psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
+                                                               noiseInterferenceW,
+                                                               payloadMode),
+                                                 current - plcpPayloadStart,
+                                                 payloadMode);
+                
+            }
+        }
+      //Case 3: previous is in HT-SIG: Non HT will not enter here since it didn't enter in the last two and they are all the same for non HT
+      else if (previous >= plcpHsigHeaderStart)
+        {
+          //Case 3a: cuurent after payload start
+          if (current >= plcpPayloadStart)
+             {
+                   psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
+                                                                   noiseInterferenceW,
+                                                                   payloadMode),
+                                                     current - plcpPayloadStart,
+                                                     payloadMode);
+                 
+              }
+
+        }
+      //Case 4: previous in L-SIG: GF will not reach here because it will execute the previous if and exit
+      else if (previous >= plcpHeaderStart)
+        {
+          //Case 4a: current after payload start  
+          if (current >= plcpPayloadStart)
+             {
+                   psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
+                                                                   noiseInterferenceW,
+                                                                   payloadMode),
+                                                     current - plcpPayloadStart,
+                                                     payloadMode);
+
+              }
+        }
+      //Case 5: previous is in the preamble works for all cases
+      else
+        {
+          if (current >= plcpPayloadStart)
+            {
+              //for all
+              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                               noiseInterferenceW,
                                                               payloadMode),
                                                 current - plcpPayloadStart,
-                                                payloadMode);
-                
-              }
+                                                payloadMode); 
+             
+            }
         }
-      //Case 3: previous is in HT-SIG: Non HT will not enter here since it didn't enter in the last two and they are all the same for non HT
-      else if (previous >=plcpHsigHeaderStart)
+
+      noiseInterferenceW += (*j).GetDelta ();
+      previous = (*j).GetTime ();
+      j++;
+    }
+
+  double per = 1 - psr;
+  return per;
+}
+
+double
+InterferenceHelper::CalculatePlcpHeaderPer (Ptr<const InterferenceHelper::Event> event, NiChanges *ni) const
+{
+  double psr = 1.0; /* Packet Success Rate */
+  NiChanges::iterator j = ni->begin ();
+  Time previous = (*j).GetTime ();
+  WifiMode payloadMode = event->GetPayloadMode ();
+  WifiPreamble preamble = event->GetPreambleType ();
+  WifiMode MfHeaderMode ;
+  if (preamble == WIFI_PREAMBLE_HT_MF)
+    {
+      MfHeaderMode = WifiPhy::GetMFPlcpHeaderMode (payloadMode, preamble); //return L-SIG mode
+    }
+  WifiMode headerMode = WifiPhy::GetPlcpHeaderMode (payloadMode, preamble);
+  Time plcpHeaderStart = (*j).GetTime () + WifiPhy::GetPlcpPreambleDuration (payloadMode, preamble); // packet start time + preamble
+  Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (payloadMode, preamble); // packet start time + preamble+L SIG
+  Time plcpHtTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble); // packet start time + preamble + L SIG + HT SIG
+  Time plcpPayloadStart = plcpHtTrainingSymbolsStart + WifiPhy::GetPlcpHtTrainingSymbolDuration (preamble, event->GetTxVector()); // packet start time + preamble + L SIG + HT SIG + Training
+  double noiseInterferenceW = (*j).GetDelta ();
+  double powerW = event->GetRxPowerW ();
+    j++;
+  while (ni->end () != j)
+    {
+      Time current = (*j).GetTime ();
+      NS_ASSERT (current >= previous);
+      //Case 1: previous is in HT-SIG: Non HT will not enter here since it didn't enter in the last two and they are all the same for non HT
+      if (previous >= plcpHsigHeaderStart)
         {
-          //Case 3a: cuurent after payload start
-          if (current >=plcpPayloadStart)
+          //Case 1a: cuurent after payload start
+          if (current >= plcpPayloadStart)
              {
-                   psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
-                                                              noiseInterferenceW,
-                                                              payloadMode),
-                                                current - plcpPayloadStart,
-                                                payloadMode);
+
                  
                     psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
-                                                              noiseInterferenceW,
-                                                              headerMode),
-                                               plcpHtTrainingSymbolsStart - previous,
-                                                headerMode);
+                                                                    noiseInterferenceW,
+                                                                    headerMode),
+                                                      plcpHtTrainingSymbolsStart - previous,
+                                                      headerMode);
               }
-          //case 3b: current after HT training symbols start
+          //case 1b: current after HT training symbols start
           else if (current >=plcpHtTrainingSymbolsStart)
              {
                 psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                                 noiseInterferenceW,
                                                                 headerMode),
-                                                   plcpHtTrainingSymbolsStart - previous,
-                                                   headerMode);  
+                                                  plcpHtTrainingSymbolsStart - previous,
+                                                  headerMode);
                    
              }
-         //Case 3c: current is with previous in HT sig
+         //Case 1c: current is with previous in HT sig
          else
             {
                 psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                                 noiseInterferenceW,
                                                                 headerMode),
-                                                   current- previous,
-                                                   headerMode);  
+                                                  current - previous,
+                                                  headerMode);
                    
             }
       }
-      //Case 4: previous in L-SIG: GF will not reach here because it will execute the previous if and exit
+      // Case 2: previous in L-SIG: GF will not reach here because it will execute the previous if and exit
       else if (previous >= plcpHeaderStart)
         {
-          //Case 4a: current after payload start  
-          if (current >=plcpPayloadStart)
+          // Case 2a: current after payload start
+          if (current >= plcpPayloadStart)
              {
-                   psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
-                                                              noiseInterferenceW,
-                                                              payloadMode),
-                                                      current - plcpPayloadStart,
-                                                      payloadMode);
-                    //Case 4ai: Non HT format (No HT-SIG or Training Symbols)
+              // Case 2ai: Non HT format (No HT-SIG or Training Symbols)
               if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT) //plcpHtTrainingSymbolsStart==plcpHeaderStart)
                 {
                     psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
-                                                              noiseInterferenceW,
-                                                              headerMode),
-                                                plcpPayloadStart - previous,
-                                                headerMode);
+                                                                    noiseInterferenceW,
+                                                                    headerMode),
+                                                      plcpPayloadStart - previous,
+                                                      headerMode);
                 }
-
-               else{
+              else
+                {
                     psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                               noiseInterferenceW,
                                                               headerMode),
@@ -389,8 +451,8 @@
                                                       MfHeaderMode);
                  }
               }
-           //Case 4b: current in HT training symbol. non HT will not come here since it went in previous if or if the previous ifis not true this will be not true        
-          else if (current >=plcpHtTrainingSymbolsStart)
+          // Case 2b: current in HT training symbol. non HT will not come here since it went in previous if or if the previous ifis not true this will be not true
+          else if (current >= plcpHtTrainingSymbolsStart)
              {
                 psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                               noiseInterferenceW,
@@ -403,8 +465,8 @@
                                                    plcpHsigHeaderStart - previous,
                                                    MfHeaderMode);
               }
-          //Case 4c: current in H sig.non HT will not come here since it went in previous if or if the previous ifis not true this will be not true
-          else if (current >=plcpHsigHeaderStart)
+          // Case 2c: current in H sig. non HT will not come here since it went in previous if or if the previous ifis not true this will be not true
+          else if (current >= plcpHsigHeaderStart)
              {
                 psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                                 noiseInterferenceW,
@@ -418,47 +480,40 @@
                                                    MfHeaderMode);
 
              }
-         //Case 4d: Current with prev in L SIG
+         // Case 2d: Current with prev in L SIG
          else 
             {
-                //Case 4di: Non HT format (No HT-SIG or Training Symbols)
+              // Case 4di: Non HT format (No HT-SIG or Training Symbols)
               if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT) //plcpHtTrainingSymbolsStart==plcpHeaderStart)
                 {
                     psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
-                                                              noiseInterferenceW,
-                                                              headerMode),
-                                                current - previous,
-                                                headerMode);
+                                                                    noiseInterferenceW,
+                                                                    headerMode),
+                                                      current - previous,
+                                                      headerMode);
                 }
-               else
+              else
                 {
-                psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
+                    psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                                noiseInterferenceW,
                                                                MfHeaderMode),
-                                                 current - previous,
-                                                 MfHeaderMode);
+                                                      current - previous,
+                                                      MfHeaderMode);
                 }
             }
         }
-      //Case 5: previous is in the preamble works for all cases
+      // Case 3: previous is in the preamble works for all cases
       else
         {
           if (current >= plcpPayloadStart)
             {
-              //for all
-              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
-                                                              noiseInterferenceW,
-                                                              payloadMode),
-                                                current - plcpPayloadStart,
-                                                payloadMode); 
-             
-               // Non HT format (No HT-SIG or Training Symbols)
+              // Non HT format (No HT-SIG or Training Symbols)
               if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT)
                  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                                  noiseInterferenceW,
-                                                                  headerMode),
-                                                    plcpPayloadStart - plcpHeaderStart,
-                                                    headerMode);
+                                                                 headerMode),
+                                                   plcpPayloadStart - plcpHeaderStart,
+                                                   headerMode);
               else
               // Greenfield or Mixed format
                 psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
@@ -473,24 +528,27 @@
                                                    plcpHsigHeaderStart-plcpHeaderStart,
                                                    MfHeaderMode);             
             }
-          else if (current >=plcpHtTrainingSymbolsStart )
+          else if (current >= plcpHtTrainingSymbolsStart )
           { 
               // Non HT format will not come here since it will execute prev if
               // Greenfield or Mixed format
-                psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
-                                                                noiseInterferenceW,
-                                                                headerMode),
-                                                  plcpHtTrainingSymbolsStart - plcpHsigHeaderStart,
-                                                  headerMode);
+              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
+                                                              noiseInterferenceW,
+                                                              headerMode),
+                                                plcpHtTrainingSymbolsStart - plcpHsigHeaderStart,
+                                                headerMode);
+              // Greenfield
               if (preamble == WIFI_PREAMBLE_HT_MF)
-                 psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
-                                                                 noiseInterferenceW,
-                                                                 MfHeaderMode),
-                                                   plcpHsigHeaderStart-plcpHeaderStart,
-                                                   MfHeaderMode);       
+                {
+                    psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
+                                                                    noiseInterferenceW,
+                                                                    MfHeaderMode),
+                                                      plcpHsigHeaderStart-plcpHeaderStart,
+                                                      MfHeaderMode);
+                }
            }
-          //non HT will not come here     
-          else if (current >=plcpHsigHeaderStart)
+          // non HT will not come here
+          else if (current >= plcpHsigHeaderStart)
              { 
                 psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                                 noiseInterferenceW,
@@ -513,17 +571,17 @@
                  {
                  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                                  noiseInterferenceW,
-                                                                  headerMode),
-                                                    current - plcpHeaderStart,
-                                                    headerMode);
+                                                                 headerMode),
+                                                   current - plcpHeaderStart,
+                                                   headerMode);
                  }
               else
                  {
               psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
                                                               noiseInterferenceW,
-                                                             MfHeaderMode),
-                                               current - plcpHeaderStart,
-                                               MfHeaderMode);
+                                                              MfHeaderMode),
+                                                current - plcpHeaderStart,
+                                                MfHeaderMode);
                        }
             }
         }
@@ -537,9 +595,8 @@
   return per;
 }
 
-
 struct InterferenceHelper::SnrPer
-InterferenceHelper::CalculateSnrPer (Ptr<InterferenceHelper::Event> event)
+InterferenceHelper::CalculatePlcpPayloadSnrPer (Ptr<InterferenceHelper::Event> event)
 {
   NiChanges ni;
   double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
@@ -550,7 +607,27 @@
   /* calculate the SNIR at the start of the packet and accumulate
    * all SNIR changes in the snir vector.
    */
-  double per = CalculatePer (event, &ni);
+  double per = CalculatePlcpPayloadPer (event, &ni);
+
+  struct SnrPer snrPer;
+  snrPer.snr = snr;
+  snrPer.per = per;
+  return snrPer;
+}
+
+struct InterferenceHelper::SnrPer
+InterferenceHelper::CalculatePlcpHeaderSnrPer (Ptr<InterferenceHelper::Event> event)
+{
+  NiChanges ni;
+  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
+  double snr = CalculateSnr (event->GetRxPowerW (),
+                             noiseInterferenceW,
+                             WifiPhy::GetPlcpHeaderMode (event->GetPayloadMode (), event->GetPreambleType ()));
+
+  /* calculate the SNIR at the start of the plcp header and accumulate
+   * all SNIR changes in the snir vector.
+   */
+  double per = CalculatePlcpHeaderPer (event, &ni);
 
   struct SnrPer snrPer;
   snrPer.snr = snr;
--- a/src/wifi/model/interference-helper.h	Sat May 02 22:21:58 2015 +0200
+++ b/src/wifi/model/interference-helper.h	Sun May 03 16:06:01 2015 +0200
@@ -182,13 +182,21 @@
                                       Time duration, double rxPower, WifiTxVector txvector);
 
   /**
-   * Calculate the SNIR at the start of the packet and accumulate
+   * Calculate the SNIR at the start of the plcp payload and accumulate
    * all SNIR changes in the snir vector.
    *
-   * \param event the event corresponding to the first time the packet arrives
+   * \param event the event corresponding to the first time the corresponding packet arrives
    * \return struct of SNR and PER
    */
-  struct InterferenceHelper::SnrPer CalculateSnrPer (Ptr<InterferenceHelper::Event> event);
+  struct InterferenceHelper::SnrPer CalculatePlcpPayloadSnrPer (Ptr<InterferenceHelper::Event> event);
+  /**
+   * Calculate the SNIR at the start of the plcp header and accumulate
+   * all SNIR changes in the snir vector.
+   *
+   * \param event the event corresponding to the first time the corresponding packet arrives
+   * \return struct of SNR and PER
+   */
+  struct InterferenceHelper::SnrPer CalculatePlcpHeaderSnrPer (Ptr<InterferenceHelper::Event> event);
   /**
    * Notify that RX has started.
    */
@@ -284,14 +292,23 @@
    */
   double CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode) const;
   /**
-   * Calculate the error rate of the given packet. The packet can be divided into
+   * Calculate the error rate of the given plcp payload. The plcp payload can be divided into
    * multiple chunks (e.g. due to interference from other transmissions).
    *
    * \param event
    * \param ni
    * \return the error rate of the packet
    */
-  double CalculatePer (Ptr<const Event> event, NiChanges *ni) const;
+  double CalculatePlcpPayloadPer (Ptr<const Event> event, NiChanges *ni) const;
+  /**
+   * Calculate the error rate of the plcp header. The plcp header can be divided into
+   * multiple chunks (e.g. due to interference from other transmissions).
+   *
+   * \param event
+   * \param ni
+   * \return the error rate of the packet
+   */
+  double CalculatePlcpHeaderPer (Ptr<const Event> event, NiChanges *ni) const;
 
   double m_noiseFigure; /**< noise figure (linear) */
   Ptr<ErrorRateModel> m_errorRateModel;
--- a/src/wifi/model/wifi-phy.cc	Sat May 02 22:21:58 2015 +0200
+++ b/src/wifi/model/wifi-phy.cc	Sun May 03 16:06:01 2015 +0200
@@ -584,6 +584,16 @@
     + GetPayloadDuration (size, txvector, preamble, frequency, packetType, incFlag);
   return duration;
 }
+Time
+WifiPhy::CalculatePlcpDuration (WifiTxVector txvector, WifiPreamble preamble)
+{
+  WifiMode payloadMode=txvector.GetMode();
+  Time duration = GetPlcpPreambleDuration (payloadMode, preamble)
+    + GetPlcpHeaderDuration (payloadMode, preamble)
+    + GetPlcpHtSigHeaderDuration (preamble)
+    + GetPlcpHtTrainingSymbolDuration (preamble, txvector);
+  return duration;
+}
 
 void
 WifiPhy::NotifyTxBegin (Ptr<const Packet> packet)
--- a/src/wifi/model/wifi-phy.h	Sat May 02 22:21:58 2015 +0200
+++ b/src/wifi/model/wifi-phy.h	Sun May 03 16:06:01 2015 +0200
@@ -295,6 +295,13 @@
    *          the transmission of these bytes.
    */
   Time CalculateTxDuration (uint32_t size, WifiTxVector txvector, enum WifiPreamble preamble, double frequency, uint8_t packetType, uint8_t incFlag);
+  
+  /**
+   * \param txvector the transmission parameters used for this packet
+   * \param preamble the type of preamble to use for this packet.
+   * \return the total amount of time this PHY will stay busy for the transmission of the plcp.
+   */
+  Time CalculatePlcpDuration (WifiTxVector txvector, enum WifiPreamble preamble);
 
   /**
    * \param preamble the type of preamble
--- a/src/wifi/model/yans-wifi-channel.cc	Sat May 02 22:21:58 2015 +0200
+++ b/src/wifi/model/yans-wifi-channel.cc	Sun May 03 16:06:01 2015 +0200
@@ -125,7 +125,7 @@
 YansWifiChannel::Receive (uint32_t i, Ptr<Packet> packet, double *atts,
                           WifiTxVector txVector, WifiPreamble preamble) const
 {
-  m_phyList[i]->StartReceivePacket (packet, *atts, txVector, preamble,*(atts+1), NanoSeconds(*(atts+2)));
+  m_phyList[i]->StartReceivePlcp (packet, *atts, txVector, preamble,*(atts+1), NanoSeconds(*(atts+2)));
   delete[] atts;
 }
 
--- a/src/wifi/model/yans-wifi-phy.cc	Sat May 02 22:21:58 2015 +0200
+++ b/src/wifi/model/yans-wifi-phy.cc	Sun May 03 16:06:01 2015 +0200
@@ -173,8 +173,10 @@
   :  m_initialized (false),
     m_channelNumber (1),
     m_endRxEvent (),
+    m_endPlcpRxEvent(),
     m_channelStartingFrequency (0),
-    m_mpdusNum(0)
+    m_mpdusNum(0),
+    m_plcpSuccess (false)
 {
   NS_LOG_FUNCTION (this);
   m_random = CreateObject<UniformRandomVariable> ();
@@ -397,6 +399,7 @@
     {
     case YansWifiPhy::RX:
       NS_LOG_DEBUG ("drop packet because of channel switching while reception");
+      m_endPlcpRxEvent.Cancel();
       m_endRxEvent.Cancel ();
       goto switchChannel;
       break;
@@ -514,19 +517,24 @@
 {
   m_state->SetReceiveErrorCallback (callback);
 }
+
 void
-YansWifiPhy::StartReceivePacket (Ptr<Packet> packet,
-                                 double rxPowerDbm,
-                                 WifiTxVector txVector,
-                                 enum WifiPreamble preamble, 
-                                 uint8_t packetType, Time rxDuration)
+YansWifiPhy::StartReceivePlcp (Ptr<Packet> packet,
+                               double rxPowerDbm,
+                               WifiTxVector txVector,
+                               enum WifiPreamble preamble,
+                               uint8_t packetType, Time rxDuration)
 {
+  // This function should be later split to check separately wether plcp preamble and plcp header can be successfully received.
+  // Note: plcp preamble reception is not yet modeled.
   NS_LOG_FUNCTION (this << packet << rxPowerDbm << txVector.GetMode()<< preamble << (uint32_t)packetType);
   AmpduTag ampduTag;
+  WifiMode txMode = txVector.GetMode();
+  
   rxPowerDbm += m_rxGainDb;
   double rxPowerW = DbmToW (rxPowerDbm);
-  WifiMode txMode = txVector.GetMode();
   Time endRx = Simulator::Now () + rxDuration;
+  Time plcpDuration = CalculatePlcpDuration (txVector, preamble);
 
   Ptr<InterferenceHelper::Event> event;
   event = m_interference.Add (packet->GetSize (),
@@ -534,13 +542,14 @@
                               preamble,
                               rxDuration,
                               rxPowerW,
-		          txVector);  // we need it to calculate duration of HT training symbols
-
+                              txVector);
+    
   switch (m_state->GetState ())
     {
     case YansWifiPhy::SWITCHING:
       NS_LOG_DEBUG ("drop packet because of channel switching");
       NotifyRxDrop (packet);
+      m_plcpSuccess = false;
       /*
        * Packets received on the upcoming channel are added to the event list
        * during the switching state. This way the medium can be correctly sensed
@@ -580,71 +589,79 @@
       break;
     case YansWifiPhy::CCA_BUSY:
     case YansWifiPhy::IDLE:
-      if (rxPowerW > m_edThresholdW)
+      if (rxPowerW > m_edThresholdW) //checked here, no need to check in the payload reception (current implementation assumes constant rx power over the packet duration)
         {
-          if (IsModeSupported (txMode) || IsMcsSupported(txMode))
+          if (preamble == WIFI_PREAMBLE_NONE && m_mpdusNum == 0)
             {
-              if (preamble != WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum == 0)
-                {
-                  //received the first MPDU in an MPDU
-                  m_mpdusNum = ampduTag.GetNoOfMpdus()-1;
-                }
-              else if (preamble == WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum > 0)
-                {
-                  //received the other MPDUs that are part of the A-MPDU
-                  if (ampduTag.GetNoOfMpdus() < m_mpdusNum)
-                    {
-                      NS_LOG_DEBUG ("Missing MPDU from the A-MPDU " << m_mpdusNum - ampduTag.GetNoOfMpdus());
-                      m_mpdusNum = ampduTag.GetNoOfMpdus();
-                    }
-                  else
-                      m_mpdusNum--;
-                }
-              else if (preamble != WIFI_PREAMBLE_NONE && m_mpdusNum > 0 )
-                {
-                  NS_LOG_DEBUG ("Didn't receive the last MPDUs from an A-MPDU " << m_mpdusNum);
-                  m_mpdusNum = 0;
-                }
-              else if (preamble == WIFI_PREAMBLE_NONE && m_mpdusNum == 0)
-                {
-                  NS_LOG_DEBUG ("drop packet because no preamble has been received");
-                  NotifyRxDrop (packet);
-                  goto maybeCcaBusy;
-                }
-              NS_LOG_DEBUG ("sync to signal (power=" << rxPowerW << "W)");
-              // sync to signal
-              m_state->SwitchToRx (rxDuration);
-              NS_ASSERT (m_endRxEvent.IsExpired ());
-              NotifyRxBegin (packet);
-              m_interference.NotifyRxStart ();
-              m_endRxEvent = Simulator::Schedule (rxDuration, &YansWifiPhy::EndReceive, this,
-                                                  packet,
-                                                  event);
+              NS_LOG_DEBUG ("drop packet because no preamble has been received");
+              NotifyRxDrop (packet);
+              goto maybeCcaBusy;
             }
-          else
+          else if (preamble == WIFI_PREAMBLE_NONE && m_plcpSuccess == false) // A-MPDU reception fails
             {
-              NS_LOG_DEBUG ("drop packet because it was sent using an unsupported mode (" << txMode << ")");
+              NS_LOG_DEBUG ("Drop MPDU because no plcp has been received");
               NotifyRxDrop (packet);
               goto maybeCcaBusy;
             }
+           else if (preamble != WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum == 0)
+            {
+              //received the first MPDU in an MPDU
+              m_mpdusNum = ampduTag.GetNoOfMpdus()-1;
+            }
+           else if (preamble == WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum > 0)
+            {
+              //received the other MPDUs that are part of the A-MPDU
+              if (ampduTag.GetNoOfMpdus() < m_mpdusNum)
+                {
+                    NS_LOG_DEBUG ("Missing MPDU from the A-MPDU " << m_mpdusNum - ampduTag.GetNoOfMpdus());
+                    m_mpdusNum = ampduTag.GetNoOfMpdus();
+                }
+              else
+                m_mpdusNum--;
+            }
+          else if (preamble != WIFI_PREAMBLE_NONE && m_mpdusNum > 0 )
+            {
+              NS_LOG_DEBUG ("Didn't receive the last MPDUs from an A-MPDU " << m_mpdusNum);
+              m_mpdusNum = 0;
+            }
+            
+          NS_LOG_DEBUG ("sync to signal (power=" << rxPowerW << "W)");
+          // sync to signal
+          m_state->SwitchToRx (rxDuration);
+          NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
+          NotifyRxBegin (packet);
+          m_interference.NotifyRxStart ();
+            
+          if (preamble != WIFI_PREAMBLE_NONE)
+          {
+            NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
+            m_endPlcpRxEvent = Simulator::Schedule (plcpDuration, &YansWifiPhy::StartReceivePacket, this,
+                                                    packet, txVector, preamble, packetType, event);
+          }
+            
+          NS_ASSERT (m_endRxEvent.IsExpired ());
+          m_endRxEvent = Simulator::Schedule (rxDuration, &YansWifiPhy::EndReceive, this,
+                                              packet, preamble, packetType, event);
         }
       else
         {
           NS_LOG_DEBUG ("drop packet because signal power too Small (" <<
                         rxPowerW << "<" << m_edThresholdW << ")");
           NotifyRxDrop (packet);
+          m_plcpSuccess = false;
           goto maybeCcaBusy;
         }
       break;
     case YansWifiPhy::SLEEP:
       NS_LOG_DEBUG ("drop packet because in sleep mode");
       NotifyRxDrop (packet);
+      m_plcpSuccess = false;
       break;
     }
 
   return;
-
-maybeCcaBusy:
+  
+  maybeCcaBusy:
   // We are here because we have received the first bit of a packet and we are
   // not going to be able to synchronize on it
   // In this model, CCA becomes busy when the aggregation of all signals as
@@ -656,6 +673,45 @@
       m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);
     }
 }
+void
+YansWifiPhy::StartReceivePacket (Ptr<Packet> packet,
+                                 WifiTxVector txVector,
+                                 enum WifiPreamble preamble, 
+                                 uint8_t packetType,
+                                 Ptr<InterferenceHelper::Event> event)
+{
+  NS_LOG_FUNCTION (this << packet << txVector.GetMode()<< preamble << (uint32_t)packetType);
+  NS_ASSERT (IsStateRx ());
+  NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
+  AmpduTag ampduTag;
+  WifiMode txMode = txVector.GetMode();
+  
+  struct InterferenceHelper::SnrPer snrPer;
+  snrPer = m_interference.CalculatePlcpHeaderSnrPer (event);
+  
+  NS_LOG_DEBUG ("snr=" << snrPer.snr << ", per=" << snrPer.per);
+
+    if (m_random->GetValue () > snrPer.per) //plcp reception succeeded
+      {
+          if (IsModeSupported (txMode) || IsMcsSupported(txMode))
+            {
+              NS_LOG_DEBUG ("receiving plcp payload"); //endReceive is already scheduled
+              m_plcpSuccess = true;
+            }
+          else //mode is not allowed
+            {
+              NS_LOG_DEBUG ("drop packet because it was sent using an unsupported mode (" << txMode << ")");
+              NotifyRxDrop (packet);
+              m_plcpSuccess = false;
+            }
+      }
+    else //plcp reception failed
+      {
+        NS_LOG_DEBUG ("drop packet because plcp reception failed");
+        NotifyRxDrop (packet);
+        m_plcpSuccess = false;
+      }
+}
 
 void
 YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType)
@@ -668,7 +724,7 @@
    *  - we are idle
    */
   NS_ASSERT (!m_state->IsStateTx () && !m_state->IsStateSwitching ());
-
+  
   if (m_state->IsStateSleep ())
     {
       NS_LOG_DEBUG ("Dropping packet because in sleep mode");
@@ -679,6 +735,7 @@
   Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, preamble, GetFrequency(), packetType, 1);
   if (m_state->IsStateRx ())
     {
+      m_endPlcpRxEvent.Cancel ();
       m_endRxEvent.Cancel ();
       m_interference.NotifyRxEnd ();
     }
@@ -948,19 +1005,22 @@
 }
 
 void
-YansWifiPhy::EndReceive (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event)
+YansWifiPhy::EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, uint8_t packetType, Ptr<InterferenceHelper::Event> event)
 {
   NS_LOG_FUNCTION (this << packet << event);
   NS_ASSERT (IsStateRx ());
   NS_ASSERT (event->GetEndTime () == Simulator::Now ());
 
   struct InterferenceHelper::SnrPer snrPer;
-  snrPer = m_interference.CalculateSnrPer (event);
+  snrPer = m_interference.CalculatePlcpPayloadSnrPer (event);
   m_interference.NotifyRxEnd ();
-
-  NS_LOG_DEBUG ("mode=" << (event->GetPayloadMode ().GetDataRate ()) <<
-                ", snr=" << snrPer.snr << ", per=" << snrPer.per << ", size=" << packet->GetSize ());
-  if (m_random->GetValue () > snrPer.per)
+  
+  if (m_plcpSuccess == true)
+  {
+    NS_LOG_DEBUG ("mode=" << (event->GetPayloadMode ().GetDataRate ()) <<
+                  ", snr=" << snrPer.snr << ", per=" << snrPer.per << ", size=" << packet->GetSize ());
+  
+    if (m_random->GetValue () > snrPer.per)
     {
       NotifyRxEnd (packet);
       uint32_t dataRate500KbpsUnits;
@@ -978,12 +1038,23 @@
       NotifyMonitorSniffRx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, isShortPreamble, signalDbm, noiseDbm);
       m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetPayloadMode (), event->GetPreambleType ());
     }
-  else
+    else
     {
       /* failure. */
       NotifyRxDrop (packet);
       m_state->SwitchFromRxEndError (packet, snrPer.snr);
     }
+  }
+  else
+  {
+    m_state->SwitchFromRxEndError (packet, snrPer.snr); //notify rx end
+  }
+    
+  if (preamble == WIFI_PREAMBLE_NONE && packetType == 2)
+    {
+      m_plcpSuccess = false;
+    }
+    
 }
 
 int64_t
--- a/src/wifi/model/yans-wifi-phy.h	Sat May 02 22:21:58 2015 +0200
+++ b/src/wifi/model/yans-wifi-phy.h	Sun May 03 16:06:01 2015 +0200
@@ -100,21 +100,35 @@
   double GetChannelFrequencyMhz () const;
 
   /**
-   * Starting receiving the packet (i.e. the first bit of the preamble has arrived).
+   * Starting receiving the plcp of a packet (i.e. the first bit of the preamble has arrived).
    *
    * \param packet the arriving packet
    * \param rxPowerDbm the receive power in dBm
    * \param txVector the TXVECTOR of the arriving packet
    * \param preamble the preamble of the arriving packet
    * \param packetType The type of the received packet (values: 0 not an A-MPDU, 1 corresponds to any packets in an A-MPDU except the last one, 2 is the last packet in an A-MPDU) 
-   * \param rxDuration the duration needed for the reception of the arriving packet
+   * \param rxDuration the duration needed for the reception of the packet
+   */
+  void StartReceivePlcp (Ptr<Packet> packet,
+                         double rxPowerDbm,
+                         WifiTxVector txVector,
+                         WifiPreamble preamble,
+                         uint8_t packetType,
+                         Time rxDuration);
+  /**
+   * Starting receiving the payload of a packet (i.e. the first bit of the packet has arrived).
+   *
+   * \param packet the arriving packet
+   * \param txVector the TXVECTOR of the arriving packet
+   * \param preamble the preamble of the arriving packet
+   * \param packetType The type of the received packet (values: 0 not an A-MPDU, 1 corresponds to any packets in an A-MPDU except the last one, 2 is the last packet in an A-MPDU) 
+   * \param event the corresponding event of the first time the packet arrives
    */
   void StartReceivePacket (Ptr<Packet> packet,
-                           double rxPowerDbm,
                            WifiTxVector txVector,
                            WifiPreamble preamble,
                            uint8_t packetType,
-                           Time rxDuration);
+                           Ptr<InterferenceHelper::Event> event);
 
   /**
    * Sets the RX loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver.
@@ -462,13 +476,15 @@
    * The last bit of the packet has arrived.
    *
    * \param packet the packet that the last bit has arrived
+   * \param preamble the preamble of the arriving packet
+   * \param packetType The type of the received packet (values: 0 not an A-MPDU, 1 corresponds to any packets in an A-MPDU except the last one, 2 is the last packet in an A-MPDU)
    * \param event the corresponding event of the first time the packet arrives
    */
-  void EndReceive (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event);
+  void EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, uint8_t packetType, Ptr<InterferenceHelper::Event> event);
 
 private:
   virtual void DoInitialize (void);
-
+  
   bool     m_initialized;         //!< Flag for runtime initialization
   double   m_edThresholdW;        //!< Energy detection threshold in watts
   double   m_ccaMode1ThresholdW;  //!< Clear channel assessment (CCA) threshold in watts
@@ -533,6 +549,7 @@
   std::vector<uint32_t> m_bssMembershipSelectorSet;
   std::vector<uint8_t> m_deviceMcsSet;
   EventId m_endRxEvent;
+  EventId m_endPlcpRxEvent;
 
   Ptr<UniformRandomVariable> m_random;  //!< Provides uniform random variables.
   double m_channelStartingFrequency;    //!< Standard-dependent center frequency of 0-th channel in MHz
@@ -540,6 +557,7 @@
   InterferenceHelper m_interference;    //!< Pointer to InterferenceHelper
   Time m_channelSwitchDelay;            //!< Time required to switch between channel
   uint16_t m_mpdusNum;                  //!< carries the number of expected mpdus that are part of an A-MPDU
+  bool m_plcpSuccess;                   //!< Flag if the PLCP of the packet or the first MPDU in an A-MPDU has been received
 };
 
 } // namespace ns3