src/devices/wifi/interference-helper.cc
changeset 4681 8558474b6149
parent 4680 a52c39181dd4
child 4684 44b325571ab4
--- a/src/devices/wifi/interference-helper.cc	Mon Jul 13 14:30:12 2009 +0200
+++ b/src/devices/wifi/interference-helper.cc	Wed Jul 15 13:06:11 2009 +0200
@@ -123,8 +123,8 @@
  ****************************************************************/
 
 InterferenceHelper::InterferenceHelper ()
-  : m_80211_standard (WIFI_PHY_STANDARD_80211a),
-    m_errorRateModel (0)
+  : m_maxPacketDuration (Seconds(0)),
+    m_errorRateModel (0)  
 {}
 InterferenceHelper::~InterferenceHelper ()
 {
@@ -145,6 +145,7 @@
      duration,
      rxPowerW);
 
+  m_maxPacketDuration = std::max(duration, m_maxPacketDuration);
   AppendEvent (event);
   return event;
 }
@@ -224,97 +225,183 @@
   return end - now;
 }
 
-Time
-InterferenceHelper::CalculateTxDuration (uint32_t size, WifiMode payloadMode, WifiPreamble preamble) const
+WifiMode 
+InterferenceHelper::GetPlcpHeaderMode (WifiMode payloadMode, WifiPreamble preamble)
 {
-  uint64_t delay = 0;
-  switch (m_80211_standard) 
-  {
+  switch (payloadMode.GetStandard ())
+    {
+    case WIFI_PHY_STANDARD_holland:
     case WIFI_PHY_STANDARD_80211a:
-    case WIFI_PHY_STANDARD_holland:
-      delay += m_plcpLongPreambleDelayUs;
-      // symbol duration is 4us
-      delay += 4;
-      delay += lrint (ceil ((size * 8.0 + 16.0 + 6.0) / payloadMode.GetDataRate () / 4e-6) * 4);
-      break;
+      // IEEE Std 802.11-2007, 17.3.2
+      // actually this is only the first part of the PlcpHeader,
+      // because the last 16 bits of the PlcpHeader are using the
+      // same mode of the payload
+      return WifiPhy::Get6mba ();      
+      
     case WIFI_PHY_STANDARD_80211b:
-      delay += m_plcpLongPreambleDelayUs;
-      delay += lrint (ceil ((size * 8.0 + 48.0) / payloadMode.GetDataRate () / 4e-6) * 4);
-      break;
-    case WIFI_PHY_STANDARD_80211_10Mhz: 
-      delay += m_plcpLongPreambleDelayUs;
-      // symbol duration is 8us
-      delay += 8;
-      delay += lrint (ceil ((size * 8.0 + 16.0 + 6.0) / payloadMode.GetDataRate () / 8e-6) * 8);
-      break;
-    case WIFI_PHY_STANDARD_80211_5Mhz: 
-      delay += m_plcpLongPreambleDelayUs;
-      // symbol duration is 16us
-      delay += 16;
-      delay += lrint (ceil ((size * 8.0 + 16.0 + 6.0) / payloadMode.GetDataRate () / 1.6e-5) * 16);
-      break;
+      if (preamble == WIFI_PREAMBLE_LONG)
+        {
+          // IEEE Std 802.11-2007, sections 15.2.3 and 18.2.2.1 
+          return WifiPhy::Get1mbb ();
+        }
+      else //  WIFI_PREAMBLE_SHORT
+        {
+          // IEEE Std 802.11-2007, section 18.2.2.2
+          return WifiPhy::Get2mbb ();
+        }
+      
+    case WIFI_PHY_STANDARD_80211_10Mhz:
+      return WifiPhy::Get3mb10Mhz ();
+      
+    case WIFI_PHY_STANDARD_80211_5Mhz:
+      return WifiPhy::Get1_5mb5Mhz ();
+    
     default:
-     NS_ASSERT (false);
-     break;
-  }
+      NS_FATAL_ERROR("unknown standard");
+      return WifiMode ();
+    }
+}
 
-  return MicroSeconds (delay);
+uint32_t
+InterferenceHelper::GetPlcpHeaderDurationMicroSeconds (WifiMode payloadMode, WifiPreamble preamble)
+{
+    switch (payloadMode.GetStandard ())
+    {
+    case WIFI_PHY_STANDARD_holland:
+    case WIFI_PHY_STANDARD_80211a:
+      // IEEE Std 802.11-2007, section 17.3.3 and figure 17-4
+      // also section 17.3.2.3, table 17-4
+      // We return the duration of the SIGNAL field only, since the
+      // SERVICE field (which strictly speaking belongs to the PLCP
+      // header, see section 17.3.2 and figure 17-1) is sent using the
+      // payload mode.  
+      return 4; 
+      
+    case WIFI_PHY_STANDARD_80211_10Mhz:
+      // IEEE Std 802.11-2007, section 17.3.2.3, table 17-4
+      return 8;
+      
+    case WIFI_PHY_STANDARD_80211_5Mhz:
+      // IEEE Std 802.11-2007, section 17.3.2.3, table 17-4
+      return 16;
+
+    case WIFI_PHY_STANDARD_80211b:
+        if (preamble == WIFI_PREAMBLE_SHORT)
+        {
+          // IEEE Std 802.11-2007, section 18.2.2.2 and figure 18-2
+          return 24;
+        }
+      else // WIFI_PREAMBLE_LONG
+        {
+          // IEEE Std 802.11-2007, sections 18.2.2.1 and figure 18-1
+          return 48;
+        }      
+      
+    default:
+      NS_FATAL_ERROR("unknown standard");
+      return 0;
+    }
+  
 }
 
-void
-InterferenceHelper::Configure80211aParameters (void)
+uint32_t 
+InterferenceHelper::GetPlcpPreambleDurationMicroSeconds (WifiMode payloadMode, WifiPreamble preamble)
 {
-  NS_LOG_FUNCTION (this);
-  m_80211_standard = WIFI_PHY_STANDARD_80211a;
-  m_plcpLongPreambleDelayUs = 16;
-  m_plcpShortPreambleDelayUs = 16;
-  m_longPlcpHeaderMode = WifiPhy::Get6mba ();
-  m_shortPlcpHeaderMode = WifiPhy::Get6mba ();
-  m_plcpHeaderLength = 4 + 1 + 12 + 1 + 6;
-  /* 4095 bytes at a 6Mb/s rate with a 1/2 coding rate. */
-  m_maxPacketDuration = CalculateTxDuration (4095, WifiPhy::Get6mba (), WIFI_PREAMBLE_LONG);
+  switch (payloadMode.GetStandard ())
+    {
+    case WIFI_PHY_STANDARD_holland:
+    case WIFI_PHY_STANDARD_80211a:
+      // IEEE Std 802.11-2007, section 17.3.3,  figure 17-4
+      // also section 17.3.2.3, table 17-4
+      return 16; 
+      
+    case WIFI_PHY_STANDARD_80211_10Mhz:
+      // IEEE Std 802.11-2007, section 17.3.3, table 17-4 
+      // also section 17.3.2.3, table 17-4
+      return 32;
+      
+    case WIFI_PHY_STANDARD_80211_5Mhz:
+      // IEEE Std 802.11-2007, section 17.3.3
+      // also section 17.3.2.3, table 17-4
+      return 64;
+
+    case WIFI_PHY_STANDARD_80211b:
+      if (preamble == WIFI_PREAMBLE_SHORT)
+        {
+          // IEEE Std 802.11-2007, section 18.2.2.2 and figure 18-2
+          return 72;
+        }
+      else // WIFI_PREAMBLE_LONG
+        {
+          // IEEE Std 802.11-2007, sections 18.2.2.1 and figure 18-1
+          return 144;
+        }
+      
+    default:
+      NS_FATAL_ERROR("unknown standard");
+      return 0;
+    }
 }
 
-void
-InterferenceHelper::Configure80211bParameters (void)
-{ 
-  NS_LOG_FUNCTION (this);
-  m_80211_standard = WIFI_PHY_STANDARD_80211b;
-  m_plcpLongPreambleDelayUs = 144;
-  m_plcpShortPreambleDelayUs = 144; // fixed preamable for 802.11b
-  m_longPlcpHeaderMode = WifiPhy::Get1mbb ();
-  m_shortPlcpHeaderMode = WifiPhy::Get1mbb ();
-  // PLCP Header: signal 8, service 8, length 16, CRC 16 bits
-  m_plcpHeaderLength = 8 + 8 + 16 + 16;
-  m_maxPacketDuration = CalculateTxDuration (4095, WifiPhy::Get1mbb (), WIFI_PREAMBLE_LONG);
+uint32_t 
+InterferenceHelper::GetPayloadDurationMicroSeconds (uint32_t size, WifiMode payloadMode)
+{
+  NS_LOG_FUNCTION(size << payloadMode);
+  switch (payloadMode.GetStandard ())
+    {
+    case WIFI_PHY_STANDARD_80211a:
+    case WIFI_PHY_STANDARD_holland:
+    case WIFI_PHY_STANDARD_80211_10Mhz: 
+    case WIFI_PHY_STANDARD_80211_5Mhz: 
+      {
+        // IEEE Std 802.11-2007, section 17.3.2.3, table 17-4
+        // corresponds to T_{SYM} in the table
+        uint32_t symbolDurationUs; 
+        switch (payloadMode.GetStandard ())
+          {       
+          case WIFI_PHY_STANDARD_holland:   
+          case WIFI_PHY_STANDARD_80211a:
+            symbolDurationUs = 4;
+            break;
+          case WIFI_PHY_STANDARD_80211_10Mhz: 
+            symbolDurationUs = 8;
+            break;
+          case WIFI_PHY_STANDARD_80211_5Mhz: 
+            symbolDurationUs = 16;
+            break;
+          default:
+            NS_FATAL_ERROR("unknown standard");
+          }
+      
+        // IEEE Std 802.11-2007, section 17.3.2.2, table 17-3
+        // corresponds to N_{DBPS} in the table
+        double numDataBitsPerSymbol = payloadMode.GetDataRate ()  * symbolDurationUs / 1e6;
+
+        // IEEE Std 802.11-2007, section 17.3.5.3, equation (17-11)
+        uint32_t numSymbols = ceil ((16 + size * 8.0 + 6.0)/numDataBitsPerSymbol);
+      
+        return numSymbols*symbolDurationUs;
+      }
+    case WIFI_PHY_STANDARD_80211b:
+      // IEEE Std 802.11-2007, section 18.2.3.5
+      NS_LOG_LOGIC(" size=" << size
+                   << " mode=" << payloadMode 
+                   << " rate=" << payloadMode.GetDataRate () );
+      return ceil ((size * 8.0) / (payloadMode.GetDataRate () / 1.0e6));
+
+    default:
+      NS_FATAL_ERROR("unknown standard");
+      return 0;
+    }
 }
 
-void
-InterferenceHelper::Configure80211_10MhzParameters (void)
+Time
+InterferenceHelper::CalculateTxDuration (uint32_t size, WifiMode payloadMode, WifiPreamble preamble) 
 {
-  NS_LOG_FUNCTION (this);
-  m_80211_standard = WIFI_PHY_STANDARD_80211_10Mhz;
-  m_plcpLongPreambleDelayUs = 32;
-  m_plcpShortPreambleDelayUs = 32;
-  m_longPlcpHeaderMode = WifiPhy::Get3mb10Mhz ();
-  m_shortPlcpHeaderMode = WifiPhy::Get3mb10Mhz ();
-  m_plcpHeaderLength = 4 + 1 + 12 + 1 + 6;
-  /* 4095 bytes at a 3Mb/s rate with a 1/2 coding rate. */
-  m_maxPacketDuration = CalculateTxDuration (4095, WifiPhy::Get3mb10Mhz (), WIFI_PREAMBLE_LONG);
-}
-
-void
-InterferenceHelper::Configure80211_5MhzParameters (void)
-{
-  NS_LOG_FUNCTION (this);
-  m_80211_standard = WIFI_PHY_STANDARD_80211_5Mhz;
-  m_plcpLongPreambleDelayUs = 64;
-  m_plcpShortPreambleDelayUs = 64;
-  m_longPlcpHeaderMode = WifiPhy::Get1_5mb5Mhz ();
-  m_shortPlcpHeaderMode = WifiPhy::Get1_5mb5Mhz ();
-  m_plcpHeaderLength = 4 + 1 + 12 + 1 + 6;
-  /* 4095 bytes at a 1.5Mb/s rate with a 1/2 coding rate. */
-  m_maxPacketDuration = CalculateTxDuration (4095, WifiPhy::Get1_5mb5Mhz (), WIFI_PREAMBLE_LONG);
+  uint32_t duration = GetPlcpPreambleDurationMicroSeconds (payloadMode, preamble)     
+                      + GetPlcpHeaderDurationMicroSeconds (payloadMode, preamble)  
+                      + GetPayloadDurationMicroSeconds (size, payloadMode);
+  return MicroSeconds (duration);
 }
 
 void 
@@ -407,29 +494,12 @@
 {  
   double psr = 1.0; /* Packet Success Rate */
   NiChanges::iterator j = ni->begin ();
-  Time previous = (*j).GetTime ();
-  uint64_t plcpPreambleDelayUs;
+  Time previous = (*j).GetTime (); 
   WifiMode payloadMode = event->GetPayloadMode ();
-  WifiMode headerMode;
-  switch (event->GetPreambleType ()) {
-  case WIFI_PREAMBLE_LONG:
-    plcpPreambleDelayUs = m_plcpLongPreambleDelayUs;
-    headerMode = m_longPlcpHeaderMode;
-    break;
-  case WIFI_PREAMBLE_SHORT:
-    plcpPreambleDelayUs = m_plcpShortPreambleDelayUs;
-    headerMode = m_shortPlcpHeaderMode;
-    break;
-  default:
-    NS_ASSERT (false);
-    // only to quiet compiler. Really stupid.
-    plcpPreambleDelayUs = 0;
-    headerMode = m_shortPlcpHeaderMode;
-    break;
-  }
-  Time plcpHeaderStart = (*j).GetTime () + MicroSeconds (plcpPreambleDelayUs);
-  Time plcpPayloadStart = plcpHeaderStart + 
-    Seconds ((m_plcpHeaderLength + 0.0) / headerMode.GetDataRate ());
+  WifiPreamble preamble = event->GetPreambleType ();
+  WifiMode headerMode = GetPlcpHeaderMode (payloadMode, preamble);
+  Time plcpHeaderStart = (*j).GetTime () + MicroSeconds (GetPlcpPreambleDurationMicroSeconds (payloadMode, preamble));
+  Time plcpPayloadStart = plcpHeaderStart + MicroSeconds (GetPlcpHeaderDurationMicroSeconds (payloadMode, preamble));
   double noiseInterferenceW = (*j).GetDelta ();
   double powerW = event->GetRxPowerW ();