802.11b PHY support
authorGary Pei <guangyu.pei@boeing.com>
Thu, 28 May 2009 20:10:27 +0200
changeset 4470 51b5c1a272d3
parent 4469 af124ed35b94
child 4471 ef1730710767
802.11b PHY support
examples/wifi-clear-channel-cmu.cc
examples/wscript
src/devices/wifi/interference-helper.cc
src/devices/wifi/interference-helper.h
src/devices/wifi/wifi-mode.cc
src/devices/wifi/wifi-mode.h
src/devices/wifi/wifi-phy-standard.h
src/devices/wifi/wifi-phy.cc
src/devices/wifi/wifi-phy.h
src/devices/wifi/wscript
src/devices/wifi/yans-error-rate-model.cc
src/devices/wifi/yans-error-rate-model.h
src/devices/wifi/yans-wifi-phy.cc
src/devices/wifi/yans-wifi-phy.h
src/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/wifi-clear-channel-cmu.cc	Thu May 28 20:10:27 2009 +0200
@@ -0,0 +1,229 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 The Boeing Company
+ *
+ * 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: Guangyu Pei <guangyu.pei@boeing.com>
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/contrib-module.h"
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+
+NS_LOG_COMPONENT_DEFINE ("Main");
+
+using namespace ns3;
+
+class Experiment
+{
+public:
+  Experiment ();
+  Experiment (std::string name);
+  uint32_t Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
+                const NqosWifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel);
+private:
+  void ReceivePacket (Ptr<Socket> socket);
+  void SetPosition (Ptr<Node> node, Vector position);
+  Vector GetPosition (Ptr<Node> node);
+  Ptr<Socket> SetupPacketReceive (Ptr<Node> node);
+  void GenerateTraffic (Ptr<Socket> socket, uint32_t pktSize, 
+                             uint32_t pktCount, Time pktInterval );
+
+  uint32_t m_pktsTotal;
+  Gnuplot2dDataset m_output;
+};
+
+Experiment::Experiment ()
+{}
+
+Experiment::Experiment (std::string name)
+  : m_output (name)
+{
+  m_output.SetStyle (Gnuplot2dDataset::LINES);
+}
+
+void
+Experiment::SetPosition (Ptr<Node> node, Vector position)
+{
+  Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
+  mobility->SetPosition (position);
+}
+
+Vector
+Experiment::GetPosition (Ptr<Node> node)
+{
+  Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
+  return mobility->GetPosition ();
+}
+
+void
+Experiment::ReceivePacket (Ptr<Socket> socket)
+{
+  Ptr<Packet> packet;
+  while (packet = socket->Recv ())
+    {
+      m_pktsTotal ++;
+    }
+}
+
+Ptr<Socket>
+Experiment::SetupPacketReceive (Ptr<Node> node)
+{
+  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+  Ptr<Socket> sink = Socket::CreateSocket (node, tid);
+  InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
+  sink->Bind (local);
+  sink->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
+  return sink;
+}
+
+void
+Experiment::GenerateTraffic (Ptr<Socket> socket, uint32_t pktSize, 
+                             uint32_t pktCount, Time pktInterval )
+{
+  if (pktCount > 0)
+    {
+      socket->Send (Create<Packet> (pktSize));
+      Simulator::Schedule (pktInterval, &Experiment::GenerateTraffic, this, 
+                           socket, pktSize,pktCount-1, pktInterval);
+    }
+  else
+    {
+      socket->Close ();
+    }
+}
+
+uint32_t
+Experiment::Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
+                 const NqosWifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel)
+{
+  m_pktsTotal = 0;
+
+  NodeContainer c;
+  c.Create (2);
+
+  InternetStackHelper internet;
+  internet.Install (c);
+
+  YansWifiPhyHelper phy = wifiPhy;
+  phy.SetChannel (wifiChannel.Create ());
+
+  NqosWifiMacHelper mac = wifiMac;
+  NetDeviceContainer devices = wifi.Install (phy, mac, c);
+
+  MobilityHelper mobility;
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
+  positionAlloc->Add (Vector (5.0, 0.0, 0.0));
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (c);
+
+  Ipv4AddressHelper ipv4;
+  NS_LOG_INFO ("Assign IP Addresses.");
+  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer i = ipv4.Assign (devices);
+
+  Ptr<Socket> recvSink = SetupPacketReceive (c.Get (0));
+
+  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+  Ptr<Socket> source = Socket::CreateSocket (c.Get (1), tid);
+  InetSocketAddress remote = InetSocketAddress (Ipv4Address ("255.255.255.255"), 80);
+  source->Connect (remote);
+  uint32_t packetSize = 1014;
+  uint32_t maxPacketCount = 200;
+  Time interPacketInterval = Seconds (1.);
+  Simulator::Schedule (Seconds (1.0), &Experiment::GenerateTraffic, 
+                       this, source, packetSize, maxPacketCount,interPacketInterval);
+  Simulator::Run ();
+
+  Simulator::Destroy ();
+
+  return m_pktsTotal;
+}
+
+int main (int argc, char *argv[])
+{
+  std::ofstream outfile ("clear-channel.plt");
+  std::vector <std::string> modes;
+
+  modes.push_back ("wifib-1mbs");
+  modes.push_back ("wifib-2mbs");
+  modes.push_back ("wifib-5.5mbs");
+  modes.push_back ("wifib-11mbs");
+  // disable fragmentation
+  Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
+  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
+
+  CommandLine cmd;
+  cmd.Parse (argc, argv);
+
+  Gnuplot gnuplot = Gnuplot ("clear-channel.eps");
+  
+  for (uint32_t i = 0; i < modes.size(); i++)
+  {
+   std::cout << modes[i] << std::endl;
+   Gnuplot2dDataset dataset (modes[i]);
+
+   for (double rss = -102.0; rss <= -80.0; rss += 0.5)
+   {
+     Experiment experiment;
+     dataset.SetStyle (Gnuplot2dDataset::LINES);
+ 
+     WifiHelper wifi;
+     NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+     Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode", 
+                         StringValue (modes[i]));
+     wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
+                                   "DataMode",StringValue(modes[i]),
+                                   "ControlMode",StringValue(modes[i]));
+     wifiMac.SetType ("ns3::AdhocWifiMac");
+ 
+     YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+     YansWifiChannelHelper wifiChannel ;
+     wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
+     wifiChannel.AddPropagationLoss ("ns3::FixedRssLossModel","Rss",DoubleValue(rss));
+ 
+ 
+     NS_LOG_DEBUG (modes[i]);
+     experiment = Experiment (modes[i]);
+     wifiPhy.Set ("Standard", StringValue ("802.11b") );
+     wifiPhy.Set ("EnergyDetectionThreshold", DoubleValue (-110.0) );
+     wifiPhy.Set ("CcaMode1Threshold", DoubleValue (-110.0) );
+     wifiPhy.Set ("TxPowerStart", DoubleValue (15.0) );
+     wifiPhy.Set ("RxGain", DoubleValue (0) ); 
+     wifiPhy.Set ("RxNoiseFigure", DoubleValue (7) ); 
+     uint32_t pktsRecvd = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel);
+     dataset.Add (rss, pktsRecvd);
+   }
+
+   gnuplot.AddDataset (dataset);
+  }
+  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
+  gnuplot.SetLegend ("RSS(dBm)", "Number of packets received");
+  gnuplot.SetExtra  ("set xrange [-102:-83]");
+  gnuplot.GenerateOutput (outfile);
+  outfile.close ();
+
+  return 0;
+}
--- a/examples/wscript	Thu May 28 20:09:28 2009 +0200
+++ b/examples/wscript	Thu May 28 20:10:27 2009 +0200
@@ -116,6 +116,10 @@
                                  ['core', 'simulator', 'mobility', 'wifi'])
     obj.source = 'wifi-adhoc.cc'
 
+    obj = bld.create_ns3_program('wifi-clear-channel-cmu',
+                                 ['core', 'simulator', 'mobility', 'wifi'])
+    obj.source = 'wifi-clear-channel-cmu.cc'
+
     obj = bld.create_ns3_program('wifi-ap',
                                  ['core', 'simulator', 'mobility', 'wifi'])
     obj.source = 'wifi-ap.cc'
--- a/src/devices/wifi/interference-helper.cc	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/interference-helper.cc	Thu May 28 20:10:27 2009 +0200
@@ -123,7 +123,7 @@
  ****************************************************************/
 
 InterferenceHelper::InterferenceHelper ()
-  : m_80211a (false),
+  : m_80211_standard (WIFI_PHY_STANDARD_80211a),
     m_errorRateModel (0)
 {}
 InterferenceHelper::~InterferenceHelper ()
@@ -227,12 +227,25 @@
 Time
 InterferenceHelper::CalculateTxDuration (uint32_t size, WifiMode payloadMode, WifiPreamble preamble) const
 {
-  NS_ASSERT (m_80211a);
   uint64_t delay = 0;
-  delay += m_plcpLongPreambleDelayUs;
-  // symbol duration is 4us
-  delay += 4;
-  delay += lrint (ceil ((size * 8.0 + 16.0 + 6.0) / payloadMode.GetDataRate () / 4e-6) * 4);
+  switch (m_80211_standard) 
+  {
+    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;
+    case WIFI_PHY_STANDARD_80211b:
+      delay += m_plcpLongPreambleDelayUs;
+      delay += lrint (ceil ((size * 8.0 + 48.0) / payloadMode.GetDataRate () / 4e-6) * 4);
+      break;
+    default:
+     NS_ASSERT (false);
+     break;
+  }
+
   return MicroSeconds (delay);
 }
 
@@ -240,7 +253,7 @@
 InterferenceHelper::Configure80211aParameters (void)
 {
   NS_LOG_FUNCTION (this);
-  m_80211a = true;
+  m_80211_standard = WIFI_PHY_STANDARD_80211a;
   m_plcpLongPreambleDelayUs = 16;
   m_plcpShortPreambleDelayUs = 16;
   m_longPlcpHeaderMode = WifiPhy::Get6mba ();
@@ -250,6 +263,20 @@
   m_maxPacketDuration = CalculateTxDuration (4095, WifiPhy::Get6mba (), WIFI_PREAMBLE_LONG);
 }
 
+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);
+}
+
 void 
 InterferenceHelper::AppendEvent (Ptr<InterferenceHelper::Event> event)
 {
--- a/src/devices/wifi/interference-helper.h	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/interference-helper.h	Thu May 28 20:10:27 2009 +0200
@@ -25,6 +25,7 @@
 #include <list>
 #include "wifi-mode.h"
 #include "wifi-preamble.h"
+#include "wifi-phy-standard.h"
 #include "ns3/nstime.h"
 #include "ns3/ref-count-base.h"
 
@@ -69,6 +70,7 @@
   ~InterferenceHelper ();
 
   void Configure80211aParameters (void);
+  void Configure80211bParameters (void);
   void SetNoiseFigure (double value);
   void SetErrorRateModel (Ptr<ErrorRateModel> rate);
 
@@ -120,7 +122,7 @@
   Time m_maxPacketDuration;
   double m_noiseFigure; /**< noise figure (linear) */
   Events m_events;
-  bool m_80211a;
+  enum WifiPhyStandard m_80211_standard;
   Ptr<ErrorRateModel> m_errorRateModel;
 };
 
--- a/src/devices/wifi/wifi-mode.cc	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/wifi-mode.cc	Thu May 28 20:10:27 2009 +0200
@@ -165,7 +165,44 @@
   item->isMandatory = isMandatory;
   return WifiMode (uid);
 }
-
+WifiMode 
+WifiModeFactory::CreateDbpsk (std::string uniqueName,
+			     bool isMandatory,
+			     uint32_t bandwidth,
+			     uint32_t dataRate,
+			     uint32_t phyRate)
+{
+  WifiModeFactory *factory = GetFactory ();
+  uint32_t uid = factory->AllocateUid (uniqueName);
+  WifiModeItem *item = factory->Get (uid);
+  item->uniqueUid = uniqueName;
+  item->bandwidth = bandwidth;
+  item->dataRate = dataRate;
+  item->phyRate = phyRate;
+  item->modulation = WifiMode::DBPSK;
+  item->constellationSize = 2;
+  item->isMandatory = isMandatory;
+  return WifiMode (uid);
+}
+WifiMode 
+WifiModeFactory::CreateDqpsk (std::string uniqueName,
+			     bool isMandatory,
+			     uint32_t bandwidth,
+			     uint32_t dataRate,
+			     uint32_t phyRate)
+{
+  WifiModeFactory *factory = GetFactory ();
+  uint32_t uid = factory->AllocateUid (uniqueName);
+  WifiModeItem *item = factory->Get (uid);
+  item->uniqueUid = uniqueName;
+  item->bandwidth = bandwidth;
+  item->dataRate = dataRate;
+  item->phyRate = phyRate;
+  item->modulation = WifiMode::DQPSK;
+  item->constellationSize = 4;
+  item->isMandatory = isMandatory;
+  return WifiMode (uid);
+}
 bool 
 WifiModeFactory::Search (std::string name, WifiMode *mode)
 {
--- a/src/devices/wifi/wifi-mode.h	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/wifi-mode.h	Thu May 28 20:10:27 2009 +0200
@@ -41,6 +41,8 @@
  public:
   enum ModulationType {
     BPSK,
+    DBPSK,
+    DQPSK,
     QAM
   };
   
@@ -170,6 +172,40 @@
 			     uint32_t phyRate,
 			     uint8_t constellationSize);
 
+  /**
+   * \param uniqueName the name of the associated WifiMode. This name
+   *        must be unique accross _all_ instances.
+   * \param isMandatory true if this WifiMode is mandatory, false otherwise.
+   * \param bandwidth the bandwidth (Hz) of the signal generated when the
+   *        associated WifiMode is used.
+   * \param dataRate the rate (bits/second) at which the user data is transmitted
+   * \param phyRate the rate (bits/second) at which the encoded user data is transmitted
+   *        The phyRate includes FEC so, is typically higher than the dataRate.
+   *
+   * Create a DBPSK WifiMode.
+   */
+  static WifiMode CreateDbpsk (std::string uniqueName,
+			      bool isMandatory,
+			      uint32_t bandwidth,
+			      uint32_t dataRate,
+			      uint32_t phyRate);
+  /**
+   * \param uniqueName the name of the associated WifiMode. This name
+   *        must be unique accross _all_ instances.
+   * \param isMandatory true if this WifiMode is mandatory, false otherwise.
+   * \param bandwidth the bandwidth (Hz) of the signal generated when the
+   *        associated WifiMode is used.
+   * \param dataRate the rate (bits/second) at which the user data is transmitted
+   * \param phyRate the rate (bits/second) at which the encoded user data is transmitted
+   *        The phyRate includes FEC so, is typically higher than the dataRate.
+   *
+   * Create a DQPSK WifiMode.
+   */
+  static WifiMode CreateDqpsk (std::string uniqueName,
+			      bool isMandatory,
+			      uint32_t bandwidth,
+			      uint32_t dataRate,
+			      uint32_t phyRate);
 private:
   friend class WifiMode;  
   friend std::istream & operator >> (std::istream &is, WifiMode &mode);
--- a/src/devices/wifi/wifi-phy-standard.h	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/wifi-phy-standard.h	Thu May 28 20:10:27 2009 +0200
@@ -24,6 +24,7 @@
 
 enum WifiPhyStandard {
   WIFI_PHY_STANDARD_80211a,
+  WIFI_PHY_STANDARD_80211b,
   WIFI_PHY_STANDARD_holland
 };
 
--- a/src/devices/wifi/wifi-phy.cc	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/wifi-phy.cc	Thu May 28 20:10:27 2009 +0200
@@ -199,6 +199,43 @@
   m_phyPromiscSnifferTrace (packet);
 }
 
+WifiMode 
+WifiPhy::Get1mbb (void)
+{
+  static WifiMode mode = WifiModeFactory::CreateDbpsk ("wifib-1mbs",
+                                                      true,
+                                                      22000000, 1000000, 1000000);
+  return mode;
+}
+
+WifiMode 
+WifiPhy::Get2mbb (void)
+{
+  static WifiMode mode = WifiModeFactory::CreateDqpsk ("wifib-2mbs",
+                                                      true,
+                                                      22000000, 2000000, 2000000);
+  return mode;
+}
+
+WifiMode 
+WifiPhy::Get5_5mbb (void)
+{
+  static WifiMode mode = WifiModeFactory::CreateDqpsk ("wifib-5.5mbs",
+                                                      true,
+                                                      22000000, 5500000, 5500000);
+  return mode;
+}
+
+WifiMode 
+WifiPhy::Get11mbb (void)
+{
+  static WifiMode mode = WifiModeFactory::CreateDqpsk ("wifib-11mbs",
+                                                      true,
+                                                      22000000, 11000000, 11000000);
+  return mode;
+}
+
+
 } // namespace ns3
 
 namespace {
@@ -215,6 +252,10 @@
     ns3::WifiPhy::Get36mba ();
     ns3::WifiPhy::Get48mba ();
     ns3::WifiPhy::Get54mba ();
+    ns3::WifiPhy::Get1mbb ();
+    ns3::WifiPhy::Get2mbb ();
+    ns3::WifiPhy::Get5_5mbb ();
+    ns3::WifiPhy::Get11mbb ();
   }
 } g_constructor;
 }
--- a/src/devices/wifi/wifi-phy.h	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/wifi-phy.h	Thu May 28 20:10:27 2009 +0200
@@ -252,6 +252,11 @@
   static WifiMode Get36mba (void);
   static WifiMode Get48mba (void);
   static WifiMode Get54mba (void);
+  static WifiMode Get1mbb (void);
+  static WifiMode Get2mbb (void);
+  static WifiMode Get5_5mbb (void);
+  static WifiMode Get11mbb (void);
+
 
   /**
    * Public method used to fire a PhyTxBegin trace.  Implemented for encapsulation 
--- a/src/devices/wifi/wscript	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/wscript	Thu May 28 20:10:27 2009 +0200
@@ -1,5 +1,12 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
+def configure(conf): 
+    have_gsl = conf.pkg_check_modules('GSL', 'gsl', mandatory=False)
+    conf.env['ENABLE_GSL'] = have_gsl
+    conf.report_optional_feature("GSL", "GNU Scientific Library (GSL)",
+                                 conf.env['ENABLE_GSL'],
+                                 "GSL not found")
+
 def build(bld):
     obj = bld.create_ns3_module('wifi', ['node'])
     obj.source = [
@@ -100,6 +107,12 @@
         'qos-tag.h',
         ]
 
+    if bld.env['ENABLE_GSL']:
+        obj.uselib = 'GSL GSLCBLAS M'
+        obj.env.append_value('CXXDEFINES', "ENABLE_GSL")
+
     obj = bld.create_ns3_program('wifi-phy-test',
         ['core', 'simulator', 'mobility', 'node', 'wifi'])
     obj.source = 'wifi-phy-test.cc'
+
+
--- a/src/devices/wifi/yans-error-rate-model.cc	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/yans-error-rate-model.cc	Thu May 28 20:10:27 2009 +0200
@@ -263,7 +263,159 @@
                            31  // adFreePlusOne
                            );
     }
+  else if (mode == WifiPhy::Get1mbb ())
+    {
+      return Get80211bDsssDbpskSuccessRate (snr,nbits);
+    }
+  else if (mode == WifiPhy::Get2mbb ())
+    {
+      return Get80211bDsssDqpskSuccessRate (snr,nbits);
+    }
+  else if (mode == WifiPhy::Get5_5mbb ())
+    {
+      return Get80211bDsssDqpskCck5_5SuccessRate (snr,nbits);
+    }
+  else if (mode == WifiPhy::Get11mbb ())
+    {
+      return Get80211bDsssDqpskCck11SuccessRate (snr,nbits);
+    }
   return 0;
 }
 
+// 802.11b ber based on "Wireless Network Coexistence: Wireless
+// LAN in the 21st Century" by Robert Morrow page 187
+double 
+YansErrorRateModel::DqpskFunction (double x) const
+{
+  return ((sqrt (2.0) + 1.0) / sqrt (8.0*3.1415926*sqrt (2.0)))
+         *(1.0/sqrt (x))
+         *exp ( - (2.0 - sqrt (2.0)) * x) ;
+}
+
+double 
+YansErrorRateModel::Get80211bDsssDbpskSuccessRate (double sinr, uint32_t nbits) const
+{
+  double EbN0 = sinr * 22000000.0 / 1000000.0; // 1 bit per symbol with 1 MSPS
+  double ber = 0.5 * exp (-EbN0);
+  return pow ((1.0 - ber), nbits);
+}
+
+double 
+YansErrorRateModel::Get80211bDsssDqpskSuccessRate (double sinr,uint32_t nbits) const
+{
+  double EbN0 = sinr * 22000000.0 / 1000000.0 / 2.0; // 2 bits per symbol, 1 MSPS
+  double ber = DqpskFunction (EbN0);
+  return pow ((1.0 - ber), nbits);
+}
+
+double 
+YansErrorRateModel::Get80211bDsssDqpskCck5_5SuccessRate (double sinr,uint32_t nbits) const
+{
+#ifdef ENABLE_GSL
+  // symbol error probability
+  double EbN0 = sinr * 22000000.0 / 1375000.0 / 4.0;
+  double sep = SymbolErrorProb16Cck (4.0*EbN0/2.0);
+  return pow (1.0-sep,nbits/4.0);
+#else
+  NS_LOG_WARN ("Running a 802.11b CCK Matlab model less accurate than GSL model"); 
+  // The matlab model
+  double ber; 
+  if (sinr > WLAN_SIR_PERFECT)
+    {
+       ber = 0.0 ;
+    }
+  else if (sinr < WLAN_SIR_IMPOSSIBLE)
+    {
+       ber = 0.5;
+    }
+  else
+    { // fitprops.coeff from matlab berfit
+       double a1 =  5.3681634344056195e-001;
+       double a2 =  3.3092430025608586e-003;
+       double a3 =  4.1654372361004000e-001;
+       double a4 =  1.0288981434358866e+000;
+       ber = a1 * exp (-(pow ((sinr-a2)/a3,a4)));
+     }
+  return pow ((1.0 - ber), nbits);
+#endif
+}
+
+double 
+YansErrorRateModel::Get80211bDsssDqpskCck11SuccessRate (double sinr,uint32_t nbits) const
+{
+#ifdef ENABLE_GSL
+ // symbol error probability
+  double EbN0 = sinr * 22000000.0 / 1375000.0 / 8.0;
+  double sep = SymbolErrorProb256Cck (8.0*EbN0/2.0);
+  return pow (1.0-sep,nbits/8.0);
+#else
+  NS_LOG_WARN ("Running a 802.11b CCK Matlab model less accurate than GSL model"); 
+  // The matlab model
+  double ber; 
+  if (sinr > WLAN_SIR_PERFECT)
+    {
+       ber = 0.0 ;
+    }
+  else if (sinr < WLAN_SIR_IMPOSSIBLE)
+    {
+       ber = 0.5;
+    }
+  else
+    { // fitprops.coeff from matlab berfit
+       double a1 =  7.9056742265333456e-003;
+       double a2 = -1.8397449399176360e-001;
+       double a3 =  1.0740689468707241e+000;
+       double a4 =  1.0523316904502553e+000;
+       double a5 =  3.0552298746496687e-001;
+       double a6 =  2.2032715128698435e+000;
+       ber =  (a1*sinr*sinr+a2*sinr+a3)/(sinr*sinr*sinr+a4*sinr*sinr+a5*sinr+a6);
+     }
+  return pow ((1.0 - ber), nbits);
+#endif
+}
+
+#ifdef ENABLE_GSL
+double 
+IntegralFunction (double x, void *params)
+{
+  double beta = ((FunctionParameters *) params)->beta;
+  double n = ((FunctionParameters *) params)->n;
+  double IntegralFunction = pow (2*gsl_cdf_ugaussian_P (x+ beta) - 1, n-1) 
+                            * exp (-x*x/2.0) / sqrt (2.0 * M_PI);
+  return IntegralFunction;
+}
+
+double 
+YansErrorRateModel::SymbolErrorProb16Cck (double e2) const
+{
+  double sep;
+  double error;
+ 
+  FunctionParameters params;
+  params.beta = sqrt (2.0*e2);
+  params.n = 8.0;
+
+  gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000); 
+ 
+  gsl_function F;
+  F.function = &IntegralFunction;
+  F.params = &params;
+
+  gsl_integration_qagiu (&F,-params.beta, 0, 1e-7, 1000, w, &sep, &error);
+  gsl_integration_workspace_free (w);
+  if (error == 0.0) 
+    {
+       sep = 1.0;
+    }
+
+  return 1.0 - sep;
+}
+
+double YansErrorRateModel::SymbolErrorProb256Cck (double e1) const
+{
+  return 1.0 - pow (1.0 - SymbolErrorProb16Cck (e1/2.0), 2.0);
+}
+
+#endif
+
 } // namespace ns3
--- a/src/devices/wifi/yans-error-rate-model.h	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/yans-error-rate-model.h	Thu May 28 20:10:27 2009 +0200
@@ -21,11 +21,51 @@
 #define YANS_ERROR_RATE_MODEL_H
 
 #include <stdint.h>
+#ifdef ENABLE_GSL
+#include <gsl/gsl_math.h>
+#include <gsl/gsl_integration.h>
+#include <gsl/gsl_cdf.h>
+#include <gsl/gsl_sf_bessel.h>
+#endif
 #include "wifi-mode.h"
 #include "error-rate-model.h"
 
 namespace ns3 {
 
+#ifdef ENABLE_GSL
+typedef struct FunctionParameterType
+{
+ double beta;
+ double n;
+} FunctionParameters;
+
+double IntegralFunction (double x, void *params);
+#endif
+
+/**
+ * \brief Model the error rate for different modulations.
+ *
+ * A packet of interest (e.g., a packet can potentially be received by the MAC) 
+ * is divided into chunks. Each chunk is related to an start/end receiving event. 
+ * For each chunk, it calculates the ratio (SINR) between received power of packet 
+ * of interest and summation of noise and interfering power of all the other incoming 
+ * packets. Then, it will calculate the success rate of the chunk based on 
+ * BER of the modulation. The success reception rate of the packet is derived from 
+ * the success rate of all chunks.
+ *
+ * The 802.11b modulations:
+ *    - 1 Mbps mode is based on DBPSK. BER is from equation 5.2-69 from John G. Proakis
+ *      Digitial Communications, 2001 edition
+ *    - 2 Mbps model is based on DQPSK. Equation 8 from "Tight bounds and accurate 
+ *      approximations for dqpsk transmission bit error rate", G. Ferrari and G.E. Corazza 
+ *      ELECTRONICS LETTERS, 40(20):1284-1285, September 2004
+ *    - 5.5 Mbps and 11 Mbps are based on equations (18) and (17) from "Properties and 
+ *      performance of the ieee 802.11b complementarycode-key signal sets", 
+ *      Michael B. Pursley and Thomas C. Royster. IEEE TRANSACTIONS ON COMMUNICATIONS, 
+ *      57(2):440-449, February 2009.
+ *    - More detailed description and validation can be found in 
+ *      http://www.nsnam.org/~pei/80211b.pdf
+ */
 class YansErrorRateModel : public ErrorRateModel
 {
 public:
@@ -52,6 +92,19 @@
                        uint32_t phyRate,
                        uint32_t m, uint32_t dfree,
                        uint32_t adFree, uint32_t adFreePlusOne) const;
+  double DqpskFunction (double x) const;
+  double Get80211bDsssDbpskSuccessRate (double sinr, uint32_t nbits) const;
+  double Get80211bDsssDqpskSuccessRate (double sinr,uint32_t nbits) const;
+  double Get80211bDsssDqpskCck5_5SuccessRate (double sinr,uint32_t nbits) const;
+  double Get80211bDsssDqpskCck11SuccessRate (double sinr,uint32_t nbits) const;
+#ifdef ENABLE_GSL
+  double SymbolErrorProb16Cck (double e2) const; /// equation (18) in Pursley's paper
+  double SymbolErrorProb256Cck (double e1) const; /// equation (17) in Pursley's paper
+#endif
+
+private:
+  static const double WLAN_SIR_PERFECT = 10.0; 
+  static const double WLAN_SIR_IMPOSSIBLE = 0.1; 
 };
 
 
--- a/src/devices/wifi/yans-wifi-phy.cc	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/yans-wifi-phy.cc	Thu May 28 20:10:27 2009 +0200
@@ -110,6 +110,7 @@
                    EnumValue (WIFI_PHY_STANDARD_80211a),
                    MakeEnumAccessor (&YansWifiPhy::SetStandard),
                    MakeEnumChecker (WIFI_PHY_STANDARD_80211a, "802.11a",
+                                    WIFI_PHY_STANDARD_80211b, "802.11b",
                                     WIFI_PHY_STANDARD_holland, "holland"))
     .AddAttribute ("State", "The state of the PHY layer",
                    PointerValue (),
@@ -150,6 +151,9 @@
   case WIFI_PHY_STANDARD_80211a:
     Configure80211a ();
     break;
+  case WIFI_PHY_STANDARD_80211b:
+    Configure80211b ();
+    break;
   case WIFI_PHY_STANDARD_holland:
     ConfigureHolland ();
     break;
@@ -440,6 +444,18 @@
   m_modes.push_back (WifiPhy::Get54mba ());
 }
 
+
+void
+YansWifiPhy::Configure80211b (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_interference.Configure80211bParameters ();
+  m_modes.push_back (WifiPhy::Get1mbb ());
+  m_modes.push_back (WifiPhy::Get2mbb ());
+  m_modes.push_back (WifiPhy::Get5_5mbb ());
+  m_modes.push_back (WifiPhy::Get11mbb ());
+}
+
 void
 YansWifiPhy::ConfigureHolland (void)
 {
--- a/src/devices/wifi/yans-wifi-phy.h	Thu May 28 20:09:28 2009 +0200
+++ b/src/devices/wifi/yans-wifi-phy.h	Thu May 28 20:10:27 2009 +0200
@@ -124,6 +124,7 @@
   YansWifiPhy (const YansWifiPhy &o);
   virtual void DoDispose (void);
   void Configure80211a (void);
+  void Configure80211b (void);
   void ConfigureHolland (void);
   double GetEdThresholdW (void) const;
   double DbmToW (double dbm) const;
--- a/src/wscript	Thu May 28 20:09:28 2009 +0200
+++ b/src/wscript	Thu May 28 20:10:27 2009 +0200
@@ -53,6 +53,7 @@
     conf.sub_config('core')
     conf.sub_config('simulator')
     conf.sub_config('devices/emu')
+    conf.sub_config('devices/wifi')
     conf.sub_config('devices/tap-bridge')
     conf.sub_config('contrib')
     conf.sub_config('internet-stack')