From 7b6bf39786b8999fdfcc71f8840b2e8d47aaa4da Mon Sep 17 00:00:00 2001 From: Gary Pei Date: Thu, 28 May 2009 20:10:27 +0200 Subject: [PATCH] 802.11b PHY support --- examples/wifi-clear-channel-cmu.cc | 229 ++++++++++++++++++++++ examples/wscript | 4 + src/devices/wifi/interference-helper.cc | 41 +++- src/devices/wifi/interference-helper.h | 4 +- src/devices/wifi/wifi-mode.cc | 39 +++- src/devices/wifi/wifi-mode.h | 36 ++++ src/devices/wifi/wifi-phy-standard.h | 1 + src/devices/wifi/wifi-phy.cc | 41 ++++ src/devices/wifi/wifi-phy.h | 5 + src/devices/wifi/wscript | 13 ++ src/devices/wifi/yans-error-rate-model.cc | 152 ++++++++++++++ src/devices/wifi/yans-error-rate-model.h | 53 +++++ src/devices/wifi/yans-wifi-phy.cc | 16 ++ src/devices/wifi/yans-wifi-phy.h | 1 + src/wscript | 1 + 15 files changed, 627 insertions(+), 9 deletions(-) create mode 100644 examples/wifi-clear-channel-cmu.cc diff --git a/examples/wifi-clear-channel-cmu.cc b/examples/wifi-clear-channel-cmu.cc new file mode 100644 index 000000000..4028d6789 --- /dev/null +++ b/examples/wifi-clear-channel-cmu.cc @@ -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 + */ + +#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 +#include +#include +#include + +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); + void SetPosition (Ptr node, Vector position); + Vector GetPosition (Ptr node); + Ptr SetupPacketReceive (Ptr node); + void GenerateTraffic (Ptr 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, Vector position) +{ + Ptr mobility = node->GetObject (); + mobility->SetPosition (position); +} + +Vector +Experiment::GetPosition (Ptr node) +{ + Ptr mobility = node->GetObject (); + return mobility->GetPosition (); +} + +void +Experiment::ReceivePacket (Ptr socket) +{ + Ptr packet; + while (packet = socket->Recv ()) + { + m_pktsTotal ++; + } +} + +Ptr +Experiment::SetupPacketReceive (Ptr node) +{ + TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); + Ptr 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, uint32_t pktSize, + uint32_t pktCount, Time pktInterval ) +{ + if (pktCount > 0) + { + socket->Send (Create (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 positionAlloc = CreateObject (); + 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 recvSink = SetupPacketReceive (c.Get (0)); + + TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); + Ptr 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 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; +} diff --git a/examples/wscript b/examples/wscript index 03ea28855..599ed8ccf 100644 --- a/examples/wscript +++ b/examples/wscript @@ -116,6 +116,10 @@ def build(bld): ['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' diff --git a/src/devices/wifi/interference-helper.cc b/src/devices/wifi/interference-helper.cc index dff6c5eb9..d1bebbebc 100644 --- a/src/devices/wifi/interference-helper.cc +++ b/src/devices/wifi/interference-helper.cc @@ -123,7 +123,7 @@ InterferenceHelper::NiChange::operator < (InterferenceHelper::NiChange const &o) ****************************************************************/ InterferenceHelper::InterferenceHelper () - : m_80211a (false), + : m_80211_standard (WIFI_PHY_STANDARD_80211a), m_errorRateModel (0) {} InterferenceHelper::~InterferenceHelper () @@ -227,12 +227,25 @@ InterferenceHelper::GetEnergyDuration (double energyW) 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 @@ void 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 @@ InterferenceHelper::Configure80211aParameters (void) 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 event) { diff --git a/src/devices/wifi/interference-helper.h b/src/devices/wifi/interference-helper.h index 0b40e239d..78f73c91b 100644 --- a/src/devices/wifi/interference-helper.h +++ b/src/devices/wifi/interference-helper.h @@ -25,6 +25,7 @@ #include #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 @@ public: ~InterferenceHelper (); void Configure80211aParameters (void); + void Configure80211bParameters (void); void SetNoiseFigure (double value); void SetErrorRateModel (Ptr rate); @@ -120,7 +122,7 @@ private: Time m_maxPacketDuration; double m_noiseFigure; /**< noise figure (linear) */ Events m_events; - bool m_80211a; + enum WifiPhyStandard m_80211_standard; Ptr m_errorRateModel; }; diff --git a/src/devices/wifi/wifi-mode.cc b/src/devices/wifi/wifi-mode.cc index 132773c28..581bcb567 100644 --- a/src/devices/wifi/wifi-mode.cc +++ b/src/devices/wifi/wifi-mode.cc @@ -165,7 +165,44 @@ WifiModeFactory::CreateQam (std::string uniqueName, 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) { diff --git a/src/devices/wifi/wifi-mode.h b/src/devices/wifi/wifi-mode.h index d0df1160a..20d707aba 100644 --- a/src/devices/wifi/wifi-mode.h +++ b/src/devices/wifi/wifi-mode.h @@ -41,6 +41,8 @@ class WifiMode public: enum ModulationType { BPSK, + DBPSK, + DQPSK, QAM }; @@ -170,6 +172,40 @@ public: 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); diff --git a/src/devices/wifi/wifi-phy-standard.h b/src/devices/wifi/wifi-phy-standard.h index 3c5828055..6893f011d 100644 --- a/src/devices/wifi/wifi-phy-standard.h +++ b/src/devices/wifi/wifi-phy-standard.h @@ -24,6 +24,7 @@ namespace ns3 { enum WifiPhyStandard { WIFI_PHY_STANDARD_80211a, + WIFI_PHY_STANDARD_80211b, WIFI_PHY_STANDARD_holland }; diff --git a/src/devices/wifi/wifi-phy.cc b/src/devices/wifi/wifi-phy.cc index 14c2e0676..3e8eee998 100644 --- a/src/devices/wifi/wifi-phy.cc +++ b/src/devices/wifi/wifi-phy.cc @@ -199,6 +199,43 @@ WifiPhy::NotifyPromiscSniff (Ptr packet) 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 @@ public: ns3::WifiPhy::Get36mba (); ns3::WifiPhy::Get48mba (); ns3::WifiPhy::Get54mba (); + ns3::WifiPhy::Get1mbb (); + ns3::WifiPhy::Get2mbb (); + ns3::WifiPhy::Get5_5mbb (); + ns3::WifiPhy::Get11mbb (); } } g_constructor; } diff --git a/src/devices/wifi/wifi-phy.h b/src/devices/wifi/wifi-phy.h index 656b3a84e..544bba317 100644 --- a/src/devices/wifi/wifi-phy.h +++ b/src/devices/wifi/wifi-phy.h @@ -252,6 +252,11 @@ public: 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 diff --git a/src/devices/wifi/wscript b/src/devices/wifi/wscript index 9218bab67..cf5bb1be7 100644 --- a/src/devices/wifi/wscript +++ b/src/devices/wifi/wscript @@ -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 @@ def build(bld): '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' + + diff --git a/src/devices/wifi/yans-error-rate-model.cc b/src/devices/wifi/yans-error-rate-model.cc index d2c810344..d46da8568 100644 --- a/src/devices/wifi/yans-error-rate-model.cc +++ b/src/devices/wifi/yans-error-rate-model.cc @@ -263,7 +263,159 @@ YansErrorRateModel::GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbi 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 = ¶ms; + + 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 diff --git a/src/devices/wifi/yans-error-rate-model.h b/src/devices/wifi/yans-error-rate-model.h index 1f9e02f94..58c9bb009 100644 --- a/src/devices/wifi/yans-error-rate-model.h +++ b/src/devices/wifi/yans-error-rate-model.h @@ -21,11 +21,51 @@ #define YANS_ERROR_RATE_MODEL_H #include +#ifdef ENABLE_GSL +#include +#include +#include +#include +#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 @@ private: 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; }; diff --git a/src/devices/wifi/yans-wifi-phy.cc b/src/devices/wifi/yans-wifi-phy.cc index f57ebdfaf..38ea922ae 100644 --- a/src/devices/wifi/yans-wifi-phy.cc +++ b/src/devices/wifi/yans-wifi-phy.cc @@ -110,6 +110,7 @@ YansWifiPhy::GetTypeId (void) 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 @@ YansWifiPhy::SetStandard (enum WifiPhyStandard standard) 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 @@ YansWifiPhy::Configure80211a (void) 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) { diff --git a/src/devices/wifi/yans-wifi-phy.h b/src/devices/wifi/yans-wifi-phy.h index 49d5c2d85..ee29a11b0 100644 --- a/src/devices/wifi/yans-wifi-phy.h +++ b/src/devices/wifi/yans-wifi-phy.h @@ -124,6 +124,7 @@ private: 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; diff --git a/src/wscript b/src/wscript index f1517e2a3..4028a6a46 100644 --- a/src/wscript +++ b/src/wscript @@ -53,6 +53,7 @@ def configure(conf): 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')