wifi: (closes #2400) Add SpectrumWifiPhy model
This commit is contained in:
13
CHANGES.html
13
CHANGES.html
@@ -54,14 +54,14 @@ us a note on ns-developers mailing list.</p>
|
||||
<h1>Changes from ns-3.25 to ns-3.26</h1>
|
||||
<h2>New API:</h2>
|
||||
<ul>
|
||||
<li>A SocketPriorityTag is introduced to carry the packet priority. Such a tag
|
||||
<li>A <b>SocketPriorityTag</b> is introduced to carry the packet priority. Such a tag
|
||||
is added to packets by sockets that support this mechanism (UdpSocketImpl,
|
||||
TcpSocketBase and PacketSocket). The base class Socket has a new SetPriority
|
||||
method to set the socket priority. When the IPv4 protocol is used, the
|
||||
priority is set based on the ToS. See the Socket options section of the
|
||||
Network model for more information.
|
||||
</li>
|
||||
<li>A WifiNetDevice::SelectQueue method has been added to determine the user
|
||||
<li>A <b>WifiNetDevice::SelectQueue</b> method has been added to determine the user
|
||||
priority of an MSDU. This method is called by the traffic control layer before
|
||||
enqueuing a packet in the queue disc, if a queue disc is installed on
|
||||
the outgoing device, or passing a packet to the device, otherwise. The
|
||||
@@ -69,11 +69,12 @@ us a note on ns-developers mailing list.</p>
|
||||
(TOS field in case of IPv4 and Traffic Class field in case of IPv6). The
|
||||
packet priority carried by the SocketPriorityTag is set to the user priority.
|
||||
</li>
|
||||
<li>The PfifoFastQueueDisc classifies packets into bands based on their priority.
|
||||
<li>The <b>PfifoFastQueueDisc</b> classifies packets into bands based on their priority.
|
||||
See the pfifo_fast queue disc section of the Traffic Control Layer model
|
||||
for more information.
|
||||
</li>
|
||||
<li>The attributes YansWifiPhy::Frequency, YansWifiPhy::ChannelNumber, and YansWifiPhy::ChannelWidth, and the related accessor methods, were moved to base class WifiPhy. YansWifiPhy::GetChannelFrequencyMhz() was deleted. A new method WifiPhy::DefineChannelNumber () was added to allow users to define relationships between channel number, standard, frequency, and channel width.
|
||||
<li> A new class <b>SpectrumWifiPhy</b> has been introduced that makes use of the Spectrum module. Its functionality and API is currently very similar to that of the YansWifiPhy, especially because it reuses the same InterferenceHelper and ErrorModel classes (for this release). Some example programs in the 'examples/wireless/' directory, such as 'wifi-spectrum-per-example.cc', illustrate how the SpectrumWifiPhy class can be substituted for the default YansWifiPhy PHY model.
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Changes to existing API:</h2>
|
||||
<ul>
|
||||
@@ -94,6 +95,10 @@ us a note on ns-developers mailing list.</p>
|
||||
</li>
|
||||
<li>The QosTag is removed as it has been superseded by the SocketPriorityTag.</li>
|
||||
<li>The Ipv4L3Protocol::DefaultTos attribute is removed.</li>
|
||||
<li>The attributes YansWifiPhy::Frequency, YansWifiPhy::ChannelNumber, and YansWifiPhy::ChannelWidth, and the related accessor methods, were moved to base class WifiPhy. YansWifiPhy::GetChannelFrequencyMhz() was deleted. A new method WifiPhy::DefineChannelNumber () was added to allow users to define relationships between channel number, standard, frequency, and channel width.
|
||||
</li>
|
||||
<li> The class <b>WifiSpectrumValueHelper</b> has been refactored; previously it was an abstract base class supporting the WifiSpectrumValue5MhzFactory spectrum model. It now contains various static member methods supporting the creation of power spectral densities with the granularity of a Wi-Fi OFDM subcarrier bandwidth. The class WifiSpectrumValue5MhzFactory and its API remain but it is not subclassed.</li>
|
||||
<li> A new method InterferenceHelper::AddForeignSignal has been introduced to support use of the SpectrumWifiPhy (so that non-Wi-Fi signals may be handled as noise power).</li>
|
||||
</ul>
|
||||
<h2>Changes to build system:</h2>
|
||||
<ul>
|
||||
|
||||
@@ -36,6 +36,11 @@ New user-visible features
|
||||
- (internet) Added TCP YeAH congestion control algorithm
|
||||
- (network) SocketAddressTag has been removed from the codebase.
|
||||
Users can use RecvFrom (for UDP) or GetPeerName (for TCP) instead.
|
||||
- (wifi) A new SpectrumWifiPhy physical layer model, making use of the
|
||||
ns-3 spectrum framework, has been introduced. The current version of
|
||||
this model matches the API and behavior of YansWifiPhy closely, but
|
||||
over time is expected to support a different PHY abstraction and error
|
||||
models.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
@@ -32,6 +32,10 @@ cpp_examples = [
|
||||
("ofdm-vht-validation", "True", "True"),
|
||||
("mixed-bg-network", "True", "True"),
|
||||
("wifi-tcp", "True", "True"),
|
||||
("wifi-spectrum-per-example --distance=52 --index=3 --wifiType=ns3::SpectrumWifiPhy --simulationTime=1", "True", "True"),
|
||||
("wifi-spectrum-per-example --distance=24 --index=31 --wifiType=ns3::YansWifiPhy --simulationTime=1", "True", "True"),
|
||||
("wifi-spectrum-per-interference --distance=24 --index=31 --simulationTime=1 --waveformPower=0.1", "True", "True"),
|
||||
("wifi-spectrum-saturation-example --simulationTime=1 --index=63", "True", "True"),
|
||||
]
|
||||
|
||||
# A list of Python examples to run in order to ensure that they remain
|
||||
|
||||
565
examples/wireless/wifi-spectrum-per-example.cc
Normal file
565
examples/wireless/wifi-spectrum-per-example.cc
Normal file
@@ -0,0 +1,565 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 MIRKO BANCHI
|
||||
* Copyright (c) 2015 University of Washington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Mirko Banchi <mk.banchi@gmail.com>
|
||||
* Sebastien Deronne <sebastien.deronne@gmail.com>
|
||||
* Tom Henderson <tomhend@u.washington.edu>
|
||||
*
|
||||
* Adapted from ht-wifi-network.cc example
|
||||
*/
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/config-store-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/wifi-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/spectrum-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
|
||||
// This is a simple example of an IEEE 802.11n Wi-Fi network.
|
||||
//
|
||||
// The main use case is to enable and test SpectrumWifiPhy vs YansWifiPhy
|
||||
// for packet error ratio
|
||||
//
|
||||
// Network topology:
|
||||
//
|
||||
// Wi-Fi 192.168.1.0
|
||||
//
|
||||
// STA AP
|
||||
// * <-- distance --> *
|
||||
// | |
|
||||
// n1 n2
|
||||
//
|
||||
// Users may vary the following command-line arguments in addition to the
|
||||
// attributes, global values, and default values typically available:
|
||||
//
|
||||
// --simulationTime: Simulation time in seconds [10]
|
||||
// --udp: UDP if set to 1, TCP otherwise [true]
|
||||
// --distance: meters separation between nodes [50]
|
||||
// --index: restrict index to single value between 0 and 31 [256]
|
||||
// --wifiType: select ns3::SpectrumWifiPhy or ns3::YansWifiPhy [ns3::SpectrumWifiPhy]
|
||||
// --errorModelType: select ns3::NistErrorRateModel or ns3::YansErrorRateModel [ns3::NistErrorRateModel]
|
||||
// --enablePcap: enable pcap output [false]
|
||||
//
|
||||
// By default, the program will step through 32 index values, corresponding
|
||||
// to the following MCS, channel width, and guard interval combinations:
|
||||
// index 0-7: MCS 0-7, long guard interval, 20 MHz channel
|
||||
// index 8-15: MCS 0-7, short guard interval, 20 MHz channel
|
||||
// index 16-23: MCS 0-7, long guard interval, 40 MHz channel
|
||||
// index 24-31: MCS 0-7, short guard interval, 40 MHz channel
|
||||
// and send 1000 UDP packets using each MCS, using the SpectrumWifiPhy and the
|
||||
// NistErrorRateModel, at a distance of 50 meters. The program outputs
|
||||
// results such as:
|
||||
//
|
||||
// wifiType: ns3::SpectrumWifiPhy distance: 50m; sent: 1000
|
||||
// index MCS Rate (Mb/s) Tput (Mb/s) Received Signal (dBm) Noise (dBm) SNR (dB)
|
||||
// 0 0 6.5 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
// 1 1 13 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
// 2 2 19.5 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
// 3 3 26 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
// ...
|
||||
//
|
||||
// When UDP is used, the throughput will always be 0.7776 Mb/s since the
|
||||
// traffic generator does not attempt to match the maximum Phy data rate
|
||||
// but instead sends at a constant rate. When TCP is used, the TCP flow
|
||||
// will exhibit different throughput depending on the index.
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
// Global variables for use in callbacks.
|
||||
double g_signalDbmAvg;
|
||||
double g_noiseDbmAvg;
|
||||
uint32_t g_samples;
|
||||
uint16_t g_channelNumber;
|
||||
uint32_t g_rate;
|
||||
|
||||
void MonitorSniffRx (Ptr<const Packet> packet, uint16_t channelFreqMhz,
|
||||
uint16_t channelNumber, uint32_t rate,
|
||||
WifiPreamble preamble, WifiTxVector txVector,
|
||||
struct mpduInfo aMpdu, struct signalNoiseDbm signalNoise)
|
||||
|
||||
{
|
||||
g_samples++;
|
||||
g_signalDbmAvg += ((signalNoise.signal - g_signalDbmAvg) / g_samples);
|
||||
g_noiseDbmAvg += ((signalNoise.noise - g_noiseDbmAvg) / g_samples);
|
||||
g_rate = rate;
|
||||
g_channelNumber = channelNumber;
|
||||
}
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("WifiSpectrumPerExample");
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
bool udp = true;
|
||||
double distance = 50;
|
||||
double simulationTime = 10; //seconds
|
||||
uint16_t index = 256;
|
||||
std::string wifiType = "ns3::SpectrumWifiPhy";
|
||||
std::string errorModelType = "ns3::NistErrorRateModel";
|
||||
bool enablePcap = false;
|
||||
const uint32_t tcpPacketSize = 1448;
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime);
|
||||
cmd.AddValue ("udp", "UDP if set to 1, TCP otherwise", udp);
|
||||
cmd.AddValue ("distance", "meters separation between nodes", distance);
|
||||
cmd.AddValue ("index", "restrict index to single value between 0 and 31", index);
|
||||
cmd.AddValue ("wifiType", "select ns3::SpectrumWifiPhy or ns3::YansWifiPhy", wifiType);
|
||||
cmd.AddValue ("errorModelType", "select ns3::NistErrorRateModel or ns3::YansErrorRateModel", errorModelType);
|
||||
cmd.AddValue ("enablePcap", "enable pcap output", enablePcap);
|
||||
cmd.Parse (argc,argv);
|
||||
|
||||
uint16_t startIndex = 0;
|
||||
uint16_t stopIndex = 31;
|
||||
if (index < 32)
|
||||
{
|
||||
startIndex = index;
|
||||
stopIndex = index;
|
||||
}
|
||||
|
||||
std::cout << "wifiType: " << wifiType << " distance: " << distance << "m; sent: 1000 TxPower: 1 dBm (1.3 mW)" << std::endl;
|
||||
std::cout << std::setw (5) << "index" <<
|
||||
std::setw (6) << "MCS" <<
|
||||
std::setw (12) << "Rate (Mb/s)" <<
|
||||
std::setw (12) << "Tput (Mb/s)" <<
|
||||
std::setw (10) << "Received " <<
|
||||
std::setw (12) << "Signal (dBm)" <<
|
||||
std::setw (12) << "Noise (dBm)" <<
|
||||
std::setw (10) << "SNR (dB)" <<
|
||||
std::endl;
|
||||
for (uint16_t i = startIndex; i <= stopIndex; i++)
|
||||
{
|
||||
uint32_t payloadSize;
|
||||
if (udp)
|
||||
{
|
||||
payloadSize = 972; // 1000 bytes IPv4
|
||||
}
|
||||
else
|
||||
{
|
||||
payloadSize = 1448; // 1500 bytes IPv6
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (payloadSize));
|
||||
}
|
||||
|
||||
NodeContainer wifiStaNode;
|
||||
wifiStaNode.Create (1);
|
||||
NodeContainer wifiApNode;
|
||||
wifiApNode.Create (1);
|
||||
|
||||
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
|
||||
SpectrumWifiPhyHelper spectrumPhy = SpectrumWifiPhyHelper::Default ();
|
||||
if (wifiType == "ns3::YansWifiPhy")
|
||||
{
|
||||
YansWifiChannelHelper channel;
|
||||
channel.AddPropagationLoss ("ns3::FriisPropagationLossModel");
|
||||
channel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
|
||||
phy.SetChannel (channel.Create ());
|
||||
phy.Set ("TxPowerStart", DoubleValue (1)); // dBm (1.26 mW)
|
||||
phy.Set ("TxPowerEnd", DoubleValue (1));
|
||||
|
||||
if (i <= 7)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
phy.Set ("ChannelWidth", UintegerValue (20));
|
||||
}
|
||||
else if (i > 7 && i <= 15)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
phy.Set ("ChannelWidth", UintegerValue (20));
|
||||
}
|
||||
else if (i > 15 && i <= 23)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
phy.Set ("ChannelWidth", UintegerValue (40));
|
||||
}
|
||||
else
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
phy.Set ("ChannelWidth", UintegerValue (40));
|
||||
}
|
||||
}
|
||||
else if (wifiType == "ns3::SpectrumWifiPhy")
|
||||
{
|
||||
Ptr<MultiModelSpectrumChannel> spectrumChannel
|
||||
= CreateObject<MultiModelSpectrumChannel> ();
|
||||
Ptr<FriisPropagationLossModel> lossModel
|
||||
= CreateObject<FriisPropagationLossModel> ();
|
||||
spectrumChannel->AddPropagationLossModel (lossModel);
|
||||
|
||||
Ptr<ConstantSpeedPropagationDelayModel> delayModel
|
||||
= CreateObject<ConstantSpeedPropagationDelayModel> ();
|
||||
spectrumChannel->SetPropagationDelayModel (delayModel);
|
||||
|
||||
spectrumPhy.SetChannel (spectrumChannel);
|
||||
spectrumPhy.SetErrorRateModel (errorModelType);
|
||||
spectrumPhy.Set ("Frequency", UintegerValue (5180));
|
||||
spectrumPhy.Set ("TxPowerStart", DoubleValue (1)); // dBm (1.26 mW)
|
||||
spectrumPhy.Set ("TxPowerEnd", DoubleValue (1));
|
||||
|
||||
if (i <= 7)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
spectrumPhy.Set ("ChannelWidth", UintegerValue (20));
|
||||
}
|
||||
else if (i > 7 && i <= 15)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
spectrumPhy.Set ("ChannelWidth", UintegerValue (20));
|
||||
}
|
||||
else if (i > 15 && i <= 23)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
spectrumPhy.Set ("ChannelWidth", UintegerValue (40));
|
||||
}
|
||||
else
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
spectrumPhy.Set ("ChannelWidth", UintegerValue (40));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unsupported WiFi type " << wifiType);
|
||||
}
|
||||
|
||||
|
||||
WifiHelper wifi;
|
||||
wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
|
||||
WifiMacHelper mac;
|
||||
|
||||
Ssid ssid = Ssid ("ns380211n");
|
||||
|
||||
double datarate = 0;
|
||||
StringValue DataRate;
|
||||
if (i == 0)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 6.5;
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 13;
|
||||
}
|
||||
else if (i == 2)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 19.5;
|
||||
}
|
||||
else if (i == 3)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 26;
|
||||
}
|
||||
else if (i == 4)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 39;
|
||||
}
|
||||
else if (i == 5)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 52;
|
||||
}
|
||||
else if (i == 6)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 58.5;
|
||||
}
|
||||
else if (i == 7)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 65;
|
||||
}
|
||||
else if (i == 8)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 7.2;
|
||||
}
|
||||
else if (i == 9)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 14.4;
|
||||
}
|
||||
else if (i == 10)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 21.7;
|
||||
}
|
||||
else if (i == 11)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 28.9;
|
||||
}
|
||||
else if (i == 12)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 43.3;
|
||||
}
|
||||
else if (i == 13)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 57.8;
|
||||
}
|
||||
else if (i == 14)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 65;
|
||||
}
|
||||
else if (i == 15)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 72.2;
|
||||
}
|
||||
else if (i == 16)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 13.5;
|
||||
}
|
||||
else if (i == 17)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 27;
|
||||
}
|
||||
else if (i == 18)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 40.5;
|
||||
}
|
||||
else if (i == 19)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 54;
|
||||
}
|
||||
else if (i == 20)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 81;
|
||||
}
|
||||
else if (i == 21)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 108;
|
||||
}
|
||||
else if (i == 22)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 121.5;
|
||||
}
|
||||
else if (i == 23)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 135;
|
||||
}
|
||||
else if (i == 24)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 15;
|
||||
}
|
||||
else if (i == 25)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 30;
|
||||
}
|
||||
else if (i == 26)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 45;
|
||||
}
|
||||
else if (i == 27)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 60;
|
||||
}
|
||||
else if (i == 28)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 90;
|
||||
}
|
||||
else if (i == 29)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 120;
|
||||
}
|
||||
else if (i == 30)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 135;
|
||||
}
|
||||
else
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 150;
|
||||
}
|
||||
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager","DataMode", DataRate,
|
||||
"ControlMode", DataRate);
|
||||
|
||||
NetDeviceContainer staDevice;
|
||||
NetDeviceContainer apDevice;
|
||||
|
||||
if (wifiType == "ns3::YansWifiPhy")
|
||||
{
|
||||
mac.SetType ("ns3::StaWifiMac",
|
||||
"Ssid", SsidValue (ssid),
|
||||
"ActiveProbing", BooleanValue (false));
|
||||
staDevice = wifi.Install (phy, mac, wifiStaNode);
|
||||
mac.SetType ("ns3::ApWifiMac",
|
||||
"Ssid", SsidValue (ssid));
|
||||
apDevice = wifi.Install (phy, mac, wifiApNode);
|
||||
|
||||
}
|
||||
else if (wifiType == "ns3::SpectrumWifiPhy")
|
||||
{
|
||||
mac.SetType ("ns3::StaWifiMac",
|
||||
"Ssid", SsidValue (ssid),
|
||||
"ActiveProbing", BooleanValue (false));
|
||||
staDevice = wifi.Install (spectrumPhy, mac, wifiStaNode);
|
||||
mac.SetType ("ns3::ApWifiMac",
|
||||
"Ssid", SsidValue (ssid));
|
||||
apDevice = wifi.Install (spectrumPhy, mac, wifiApNode);
|
||||
}
|
||||
|
||||
// mobility.
|
||||
MobilityHelper mobility;
|
||||
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
|
||||
|
||||
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
|
||||
positionAlloc->Add (Vector (distance, 0.0, 0.0));
|
||||
mobility.SetPositionAllocator (positionAlloc);
|
||||
|
||||
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
||||
|
||||
mobility.Install (wifiApNode);
|
||||
mobility.Install (wifiStaNode);
|
||||
|
||||
/* Internet stack*/
|
||||
InternetStackHelper stack;
|
||||
stack.Install (wifiApNode);
|
||||
stack.Install (wifiStaNode);
|
||||
|
||||
Ipv4AddressHelper address;
|
||||
|
||||
address.SetBase ("192.168.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer staNodeInterface;
|
||||
Ipv4InterfaceContainer apNodeInterface;
|
||||
|
||||
staNodeInterface = address.Assign (staDevice);
|
||||
apNodeInterface = address.Assign (apDevice);
|
||||
|
||||
/* Setting applications */
|
||||
ApplicationContainer serverApp, sinkApp;
|
||||
if (udp)
|
||||
{
|
||||
//UDP flow
|
||||
UdpServerHelper myServer (9);
|
||||
serverApp = myServer.Install (wifiStaNode.Get (0));
|
||||
serverApp.Start (Seconds (0.0));
|
||||
serverApp.Stop (Seconds (simulationTime + 1));
|
||||
|
||||
UdpClientHelper myClient (staNodeInterface.GetAddress (0), 9);
|
||||
myClient.SetAttribute ("MaxPackets", UintegerValue (1000));
|
||||
myClient.SetAttribute ("Interval", TimeValue (MilliSeconds (5)));
|
||||
myClient.SetAttribute ("PacketSize", UintegerValue (payloadSize));
|
||||
|
||||
ApplicationContainer clientApp = myClient.Install (wifiApNode.Get (0));
|
||||
clientApp.Start (Seconds (1.0));
|
||||
clientApp.Stop (Seconds (simulationTime + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
//TCP flow
|
||||
uint16_t port = 50000;
|
||||
Address apLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", apLocalAddress);
|
||||
sinkApp = packetSinkHelper.Install (wifiStaNode.Get (0));
|
||||
|
||||
sinkApp.Start (Seconds (0.0));
|
||||
sinkApp.Stop (Seconds (simulationTime + 1));
|
||||
|
||||
OnOffHelper onoff ("ns3::TcpSocketFactory",Ipv4Address::GetAny ());
|
||||
onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onoff.SetAttribute ("PacketSize", UintegerValue (payloadSize));
|
||||
onoff.SetAttribute ("DataRate", DataRateValue (1000000000)); //bit/s
|
||||
ApplicationContainer apps;
|
||||
|
||||
AddressValue remoteAddress (InetSocketAddress (staNodeInterface.GetAddress (0), port));
|
||||
onoff.SetAttribute ("Remote", remoteAddress);
|
||||
apps.Add (onoff.Install (wifiApNode.Get (0)));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (simulationTime + 1));
|
||||
}
|
||||
|
||||
Config::ConnectWithoutContext ("/NodeList/0/DeviceList/*/Phy/MonitorSnifferRx", MakeCallback (&MonitorSniffRx));
|
||||
|
||||
if (enablePcap)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "wifi-spectrum-per-example-" << i;
|
||||
phy.EnablePcap (ss.str (), apDevice);
|
||||
}
|
||||
g_signalDbmAvg = 0;
|
||||
g_noiseDbmAvg = 0;
|
||||
g_samples = 0;
|
||||
g_channelNumber = 0;
|
||||
g_rate = 0;
|
||||
|
||||
Simulator::Stop (Seconds (simulationTime + 1));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
double throughput = 0;
|
||||
uint32_t totalPacketsThrough = 0;
|
||||
if (udp)
|
||||
{
|
||||
//UDP
|
||||
totalPacketsThrough = DynamicCast<UdpServer> (serverApp.Get (0))->GetReceived ();
|
||||
throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); //Mbit/s
|
||||
}
|
||||
else
|
||||
{
|
||||
//TCP
|
||||
uint32_t totalBytesRx = DynamicCast<PacketSink> (sinkApp.Get (0))->GetTotalRx ();
|
||||
totalPacketsThrough = totalBytesRx / tcpPacketSize;
|
||||
throughput = totalBytesRx * 8 / (simulationTime * 1000000.0); //Mbit/s
|
||||
}
|
||||
std::cout << std::setw (5) << i <<
|
||||
std::setw (6) << (i % 8) <<
|
||||
std::setw (10) << datarate <<
|
||||
std::setw (12) << throughput <<
|
||||
std::setw (8) << totalPacketsThrough;
|
||||
if (totalPacketsThrough > 0)
|
||||
{
|
||||
std::cout << std::setw (12) << g_signalDbmAvg <<
|
||||
std::setw (12) << g_noiseDbmAvg <<
|
||||
std::setw (12) << (g_signalDbmAvg - g_noiseDbmAvg) <<
|
||||
std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << std::setw (12) << "N/A" <<
|
||||
std::setw (12) << "N/A" <<
|
||||
std::setw (12) << "N/A" <<
|
||||
std::endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
627
examples/wireless/wifi-spectrum-per-interference.cc
Normal file
627
examples/wireless/wifi-spectrum-per-interference.cc
Normal file
@@ -0,0 +1,627 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 MIRKO BANCHI
|
||||
* Copyright (c) 2015 University of Washington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Mirko Banchi <mk.banchi@gmail.com>
|
||||
* Sebastien Deronne <sebastien.deronne@gmail.com>
|
||||
* Tom Henderson <tomhend@u.washington.edu>
|
||||
*
|
||||
* Adapted from ht-wifi-network.cc example
|
||||
*/
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/config-store-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/wifi-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/spectrum-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
|
||||
// This is a simple example of an IEEE 802.11n Wi-Fi network with a
|
||||
// non-Wi-Fi interferer. It is an adaptation of the wifi-spectrum-per-example
|
||||
//
|
||||
// Unless the --waveformPower argument is passed, it will behave like
|
||||
// wifi-spectrum-per-example. Adding --waveformPower=value for values
|
||||
// greater than 0.0001 will result in frame losses beyond those that
|
||||
// result from the normal SNR based on distance path loss.
|
||||
//
|
||||
// If YansWifiPhy is selected as the wifiType, --waveformPower will have
|
||||
// no effect.
|
||||
//
|
||||
// Network topology:
|
||||
//
|
||||
// Wi-Fi 192.168.1.0
|
||||
//
|
||||
// STA AP
|
||||
// * <-- distance --> *
|
||||
// | |
|
||||
// n1 n2
|
||||
//
|
||||
// Users may vary the following command-line arguments in addition to the
|
||||
// attributes, global values, and default values typically available:
|
||||
//
|
||||
// --simulationTime: Simulation time in seconds [10]
|
||||
// --udp: UDP if set to 1, TCP otherwise [true]
|
||||
// --distance: meters separation between nodes [50]
|
||||
// --index: restrict index to single value between 0 and 31 [256]
|
||||
// --wifiType: select ns3::SpectrumWifiPhy or ns3::YansWifiPhy [ns3::SpectrumWifiPhy]
|
||||
// --errorModelType: select ns3::NistErrorRateModel or ns3::YansErrorRateModel [ns3::NistErrorRateModel]
|
||||
// --enablePcap: enable pcap output [false]
|
||||
// --waveformPower: Waveform power [0]
|
||||
//
|
||||
// By default, the program will step through 32 index values, corresponding
|
||||
// to the following MCS, channel width, and guard interval combinations:
|
||||
// index 0-7: MCS 0-7, long guard interval, 20 MHz channel
|
||||
// index 8-15: MCS 0-7, short guard interval, 20 MHz channel
|
||||
// index 16-23: MCS 0-7, long guard interval, 40 MHz channel
|
||||
// index 24-31: MCS 0-7, short guard interval, 40 MHz channel
|
||||
// and send 1000 UDP packets using each MCS, using the SpectrumWifiPhy and the
|
||||
// NistErrorRateModel, at a distance of 50 meters. The program outputs
|
||||
// results such as:
|
||||
//
|
||||
// wifiType: ns3::SpectrumWifiPhy distance: 50m; sent: 1000
|
||||
// index MCS Rate (Mb/s) Tput (Mb/s) Received Signal (dBm) Noise (dBm) SNR (dB)
|
||||
// 0 0 6.5 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
// 1 1 13 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
// 2 2 19.5 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
// 3 3 26 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
// ...
|
||||
//
|
||||
// When UDP is used, the throughput will always be 0.7776 Mb/s since the
|
||||
// traffic generator does not attempt to match the maximum Phy data rate
|
||||
// but instead sends at a constant rate. When TCP is used, the TCP flow
|
||||
// will exhibit different throughput depending on the index.
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
// Global variables for use in callbacks.
|
||||
double g_signalDbmAvg;
|
||||
double g_noiseDbmAvg;
|
||||
uint32_t g_samples;
|
||||
uint16_t g_channelNumber;
|
||||
uint32_t g_rate;
|
||||
|
||||
void MonitorSniffRx (Ptr<const Packet> packet, uint16_t channelFreqMhz,
|
||||
uint16_t channelNumber, uint32_t rate,
|
||||
WifiPreamble preamble, WifiTxVector txVector,
|
||||
struct mpduInfo aMpdu, struct signalNoiseDbm signalNoise)
|
||||
|
||||
{
|
||||
g_samples++;
|
||||
g_signalDbmAvg += ((signalNoise.signal - g_signalDbmAvg) / g_samples);
|
||||
g_noiseDbmAvg += ((signalNoise.noise - g_noiseDbmAvg) / g_samples);
|
||||
g_rate = rate;
|
||||
g_channelNumber = channelNumber;
|
||||
}
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("WifiSpectrumPerInterference");
|
||||
|
||||
Ptr<SpectrumModel> SpectrumModelWifi5180MHz;
|
||||
|
||||
class static_SpectrumModelWifi5180MHz_initializer
|
||||
{
|
||||
public:
|
||||
static_SpectrumModelWifi5180MHz_initializer ()
|
||||
{
|
||||
BandInfo bandInfo;
|
||||
bandInfo.fc = 5180e6;
|
||||
bandInfo.fl = 5180e6 - 10e6;
|
||||
bandInfo.fh = 5180e6 + 10e6;
|
||||
|
||||
Bands bands;
|
||||
bands.push_back (bandInfo);
|
||||
|
||||
SpectrumModelWifi5180MHz = Create<SpectrumModel> (bands);
|
||||
}
|
||||
|
||||
} static_SpectrumModelWifi5180MHz_initializer_instance;
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
bool udp = true;
|
||||
double distance = 50;
|
||||
double simulationTime = 10; //seconds
|
||||
uint16_t index = 256;
|
||||
std::string wifiType = "ns3::SpectrumWifiPhy";
|
||||
std::string errorModelType = "ns3::NistErrorRateModel";
|
||||
bool enablePcap = false;
|
||||
const uint32_t tcpPacketSize = 1448;
|
||||
double waveformPower = 0;
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime);
|
||||
cmd.AddValue ("udp", "UDP if set to 1, TCP otherwise", udp);
|
||||
cmd.AddValue ("distance", "meters separation between nodes", distance);
|
||||
cmd.AddValue ("index", "restrict index to single value between 0 and 31", index);
|
||||
cmd.AddValue ("wifiType", "select ns3::SpectrumWifiPhy or ns3::YansWifiPhy", wifiType);
|
||||
cmd.AddValue ("errorModelType", "select ns3::NistErrorRateModel or ns3::YansErrorRateModel", errorModelType);
|
||||
cmd.AddValue ("enablePcap", "enable pcap output", enablePcap);
|
||||
cmd.AddValue ("waveformPower", "Waveform power", waveformPower);
|
||||
cmd.Parse (argc,argv);
|
||||
|
||||
uint16_t startIndex = 0;
|
||||
uint16_t stopIndex = 31;
|
||||
if (index < 32)
|
||||
{
|
||||
startIndex = index;
|
||||
stopIndex = index;
|
||||
}
|
||||
|
||||
std::cout << "wifiType: " << wifiType << " distance: " << distance << "m; sent: 1000 TxPower: 16 dBm (40 mW)" << std::endl;
|
||||
std::cout << std::setw (5) << "index" <<
|
||||
std::setw (6) << "MCS" <<
|
||||
std::setw (12) << "Rate (Mb/s)" <<
|
||||
std::setw (12) << "Tput (Mb/s)" <<
|
||||
std::setw (10) << "Received " <<
|
||||
std::setw (12) << "Signal (dBm)" <<
|
||||
std::setw (12) << "Noi+Inf(dBm)" <<
|
||||
std::setw (10) << "SNR (dB)" <<
|
||||
std::endl;
|
||||
for (uint16_t i = startIndex; i <= stopIndex; i++)
|
||||
{
|
||||
uint32_t payloadSize;
|
||||
if (udp)
|
||||
{
|
||||
payloadSize = 972; // 1000 bytes IPv4
|
||||
}
|
||||
else
|
||||
{
|
||||
payloadSize = 1448; // 1500 bytes IPv6
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (payloadSize));
|
||||
}
|
||||
|
||||
NodeContainer wifiStaNode;
|
||||
wifiStaNode.Create (1);
|
||||
NodeContainer wifiApNode;
|
||||
wifiApNode.Create (1);
|
||||
NodeContainer interferingNode;
|
||||
interferingNode.Create (1);
|
||||
|
||||
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
|
||||
SpectrumWifiPhyHelper spectrumPhy = SpectrumWifiPhyHelper::Default ();
|
||||
Ptr<MultiModelSpectrumChannel> spectrumChannel;
|
||||
if (wifiType == "ns3::YansWifiPhy")
|
||||
{
|
||||
YansWifiChannelHelper channel;
|
||||
channel.AddPropagationLoss ("ns3::FriisPropagationLossModel");
|
||||
channel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
|
||||
phy.SetChannel (channel.Create ());
|
||||
phy.Set ("Frequency", UintegerValue (5180));
|
||||
|
||||
if (i <= 7)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
phy.Set ("ChannelWidth", UintegerValue (20));
|
||||
}
|
||||
else if (i > 7 && i <= 15)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
phy.Set ("ChannelWidth", UintegerValue (20));
|
||||
}
|
||||
else if (i > 15 && i <= 23)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
phy.Set ("ChannelWidth", UintegerValue (40));
|
||||
}
|
||||
else
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
phy.Set ("ChannelWidth", UintegerValue (40));
|
||||
}
|
||||
}
|
||||
else if (wifiType == "ns3::SpectrumWifiPhy")
|
||||
{
|
||||
spectrumChannel
|
||||
= CreateObject<MultiModelSpectrumChannel> ();
|
||||
Ptr<FriisPropagationLossModel> lossModel
|
||||
= CreateObject<FriisPropagationLossModel> ();
|
||||
spectrumChannel->AddPropagationLossModel (lossModel);
|
||||
|
||||
|
||||
Ptr<ConstantSpeedPropagationDelayModel> delayModel
|
||||
= CreateObject<ConstantSpeedPropagationDelayModel> ();
|
||||
spectrumChannel->SetPropagationDelayModel (delayModel);
|
||||
|
||||
spectrumPhy.SetChannel (spectrumChannel);
|
||||
spectrumPhy.SetErrorRateModel (errorModelType);
|
||||
spectrumPhy.Set ("Frequency", UintegerValue (5180)); // channel 36 at 20 MHz
|
||||
|
||||
if (i <= 7)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
spectrumPhy.Set ("ChannelWidth", UintegerValue (20));
|
||||
}
|
||||
else if (i > 7 && i <= 15)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
spectrumPhy.Set ("ChannelWidth", UintegerValue (20));
|
||||
}
|
||||
else if (i > 15 && i <= 23)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
spectrumPhy.Set ("ChannelWidth", UintegerValue (40));
|
||||
}
|
||||
else
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
spectrumPhy.Set ("ChannelWidth", UintegerValue (40));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unsupported WiFi type " << wifiType);
|
||||
}
|
||||
|
||||
|
||||
WifiHelper wifi;
|
||||
wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
|
||||
WifiMacHelper mac;
|
||||
|
||||
Ssid ssid = Ssid ("ns380211n");
|
||||
|
||||
double datarate = 0;
|
||||
StringValue DataRate;
|
||||
if (i == 0)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 6.5;
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 13;
|
||||
}
|
||||
else if (i == 2)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 19.5;
|
||||
}
|
||||
else if (i == 3)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 26;
|
||||
}
|
||||
else if (i == 4)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 39;
|
||||
}
|
||||
else if (i == 5)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 52;
|
||||
}
|
||||
else if (i == 6)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 58.5;
|
||||
}
|
||||
else if (i == 7)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 65;
|
||||
}
|
||||
else if (i == 8)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 7.2;
|
||||
}
|
||||
else if (i == 9)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 14.4;
|
||||
}
|
||||
else if (i == 10)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 21.7;
|
||||
}
|
||||
else if (i == 11)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 28.9;
|
||||
}
|
||||
else if (i == 12)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 43.3;
|
||||
}
|
||||
else if (i == 13)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 57.8;
|
||||
}
|
||||
else if (i == 14)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 65;
|
||||
}
|
||||
else if (i == 15)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 72.2;
|
||||
}
|
||||
else if (i == 16)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 13.5;
|
||||
}
|
||||
else if (i == 17)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 27;
|
||||
}
|
||||
else if (i == 18)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 40.5;
|
||||
}
|
||||
else if (i == 19)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 54;
|
||||
}
|
||||
else if (i == 20)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 81;
|
||||
}
|
||||
else if (i == 21)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 108;
|
||||
}
|
||||
else if (i == 22)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 121.5;
|
||||
}
|
||||
else if (i == 23)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 135;
|
||||
}
|
||||
else if (i == 24)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 15;
|
||||
}
|
||||
else if (i == 25)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 30;
|
||||
}
|
||||
else if (i == 26)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 45;
|
||||
}
|
||||
else if (i == 27)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 60;
|
||||
}
|
||||
else if (i == 28)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 90;
|
||||
}
|
||||
else if (i == 29)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 120;
|
||||
}
|
||||
else if (i == 30)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 135;
|
||||
}
|
||||
else
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 150;
|
||||
}
|
||||
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager","DataMode", DataRate,
|
||||
"ControlMode", DataRate);
|
||||
|
||||
NetDeviceContainer staDevice;
|
||||
NetDeviceContainer apDevice;
|
||||
|
||||
if (wifiType == "ns3::YansWifiPhy")
|
||||
{
|
||||
mac.SetType ("ns3::StaWifiMac",
|
||||
"Ssid", SsidValue (ssid),
|
||||
"ActiveProbing", BooleanValue (false));
|
||||
staDevice = wifi.Install (phy, mac, wifiStaNode);
|
||||
mac.SetType ("ns3::ApWifiMac",
|
||||
"Ssid", SsidValue (ssid));
|
||||
apDevice = wifi.Install (phy, mac, wifiApNode);
|
||||
|
||||
}
|
||||
else if (wifiType == "ns3::SpectrumWifiPhy")
|
||||
{
|
||||
mac.SetType ("ns3::StaWifiMac",
|
||||
"Ssid", SsidValue (ssid),
|
||||
"ActiveProbing", BooleanValue (false));
|
||||
staDevice = wifi.Install (spectrumPhy, mac, wifiStaNode);
|
||||
mac.SetType ("ns3::ApWifiMac",
|
||||
"Ssid", SsidValue (ssid));
|
||||
apDevice = wifi.Install (spectrumPhy, mac, wifiApNode);
|
||||
}
|
||||
|
||||
// mobility.
|
||||
MobilityHelper mobility;
|
||||
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
|
||||
|
||||
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
|
||||
positionAlloc->Add (Vector (distance, 0.0, 0.0));
|
||||
positionAlloc->Add (Vector (distance, distance, 0.0));
|
||||
mobility.SetPositionAllocator (positionAlloc);
|
||||
|
||||
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
||||
|
||||
mobility.Install (wifiApNode);
|
||||
mobility.Install (wifiStaNode);
|
||||
mobility.Install (interferingNode);
|
||||
|
||||
/* Internet stack*/
|
||||
InternetStackHelper stack;
|
||||
stack.Install (wifiApNode);
|
||||
stack.Install (wifiStaNode);
|
||||
|
||||
Ipv4AddressHelper address;
|
||||
|
||||
address.SetBase ("192.168.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer staNodeInterface;
|
||||
Ipv4InterfaceContainer apNodeInterface;
|
||||
|
||||
staNodeInterface = address.Assign (staDevice);
|
||||
apNodeInterface = address.Assign (apDevice);
|
||||
|
||||
/* Setting applications */
|
||||
ApplicationContainer serverApp, sinkApp;
|
||||
if (udp)
|
||||
{
|
||||
//UDP flow
|
||||
UdpServerHelper myServer (9);
|
||||
serverApp = myServer.Install (wifiStaNode.Get (0));
|
||||
serverApp.Start (Seconds (0.0));
|
||||
serverApp.Stop (Seconds (simulationTime + 1));
|
||||
|
||||
UdpClientHelper myClient (staNodeInterface.GetAddress (0), 9);
|
||||
myClient.SetAttribute ("MaxPackets", UintegerValue (1000));
|
||||
myClient.SetAttribute ("Interval", TimeValue (MilliSeconds (5)));
|
||||
myClient.SetAttribute ("PacketSize", UintegerValue (payloadSize));
|
||||
|
||||
ApplicationContainer clientApp = myClient.Install (wifiApNode.Get (0));
|
||||
clientApp.Start (Seconds (1.0));
|
||||
clientApp.Stop (Seconds (simulationTime + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
//TCP flow
|
||||
uint16_t port = 50000;
|
||||
Address apLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", apLocalAddress);
|
||||
sinkApp = packetSinkHelper.Install (wifiStaNode.Get (0));
|
||||
|
||||
sinkApp.Start (Seconds (0.0));
|
||||
sinkApp.Stop (Seconds (simulationTime + 1));
|
||||
|
||||
OnOffHelper onoff ("ns3::TcpSocketFactory",Ipv4Address::GetAny ());
|
||||
onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onoff.SetAttribute ("PacketSize", UintegerValue (payloadSize));
|
||||
onoff.SetAttribute ("DataRate", DataRateValue (1000000000)); //bit/s
|
||||
ApplicationContainer apps;
|
||||
|
||||
AddressValue remoteAddress (InetSocketAddress (staNodeInterface.GetAddress (0), port));
|
||||
onoff.SetAttribute ("Remote", remoteAddress);
|
||||
apps.Add (onoff.Install (wifiApNode.Get (0)));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (simulationTime + 1));
|
||||
}
|
||||
// Configure waveform generator
|
||||
|
||||
Ptr<SpectrumValue> wgPsd = Create<SpectrumValue> (SpectrumModelWifi5180MHz);
|
||||
*wgPsd = waveformPower / (100 * 180000);
|
||||
NS_LOG_INFO ("wgPsd : " << *wgPsd << " integrated power: " << Integral (*(GetPointer (wgPsd))));
|
||||
|
||||
if (wifiType == "ns3::SpectrumWifiPhy")
|
||||
{
|
||||
WaveformGeneratorHelper waveformGeneratorHelper;
|
||||
waveformGeneratorHelper.SetChannel (spectrumChannel);
|
||||
waveformGeneratorHelper.SetTxPowerSpectralDensity (wgPsd);
|
||||
|
||||
waveformGeneratorHelper.SetPhyAttribute ("Period", TimeValue (Seconds (0.0007)));
|
||||
waveformGeneratorHelper.SetPhyAttribute ("DutyCycle", DoubleValue (1));
|
||||
NetDeviceContainer waveformGeneratorDevices = waveformGeneratorHelper.Install (interferingNode);
|
||||
|
||||
Simulator::Schedule (Seconds (0.002), &WaveformGenerator::Start,
|
||||
waveformGeneratorDevices.Get (0)->GetObject<NonCommunicatingNetDevice> ()->GetPhy ()->GetObject<WaveformGenerator> ());
|
||||
}
|
||||
|
||||
Config::ConnectWithoutContext ("/NodeList/0/DeviceList/*/Phy/MonitorSnifferRx", MakeCallback (&MonitorSniffRx));
|
||||
|
||||
if (enablePcap)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "wifi-spectrum-per-example-" << i;
|
||||
phy.EnablePcap (ss.str (), apDevice);
|
||||
}
|
||||
g_signalDbmAvg = 0;
|
||||
g_noiseDbmAvg = 0;
|
||||
g_samples = 0;
|
||||
g_channelNumber = 0;
|
||||
g_rate = 0;
|
||||
|
||||
// Make sure we are tuned to 5180 MHz; if not, the example will
|
||||
// not work properly
|
||||
Ptr<NetDevice> staDevicePtr = staDevice.Get (0);
|
||||
Ptr<WifiNetDevice> wifiStaDevicePtr = staDevicePtr->GetObject <WifiNetDevice> ();
|
||||
UintegerValue val;
|
||||
wifiStaDevicePtr->GetPhy ()->GetAttribute ("Frequency", val);
|
||||
if (val.Get () != 5180)
|
||||
{
|
||||
NS_FATAL_ERROR ("Error: Wi-Fi nodes must be tuned to 5180 MHz to match the waveform generator");
|
||||
}
|
||||
|
||||
Simulator::Stop (Seconds (simulationTime + 1));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
double throughput = 0;
|
||||
uint32_t totalPacketsThrough = 0;
|
||||
if (udp)
|
||||
{
|
||||
//UDP
|
||||
totalPacketsThrough = DynamicCast<UdpServer> (serverApp.Get (0))->GetReceived ();
|
||||
throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); //Mbit/s
|
||||
}
|
||||
else
|
||||
{
|
||||
//TCP
|
||||
uint32_t totalBytesRx = DynamicCast<PacketSink> (sinkApp.Get (0))->GetTotalRx ();
|
||||
totalPacketsThrough = totalBytesRx / tcpPacketSize;
|
||||
throughput = totalBytesRx * 8 / (simulationTime * 1000000.0); //Mbit/s
|
||||
}
|
||||
std::cout << std::setw (5) << i <<
|
||||
std::setw (6) << (i % 8) <<
|
||||
std::setw (10) << datarate <<
|
||||
std::setw (12) << throughput <<
|
||||
std::setw (8) << totalPacketsThrough;
|
||||
if (totalPacketsThrough > 0)
|
||||
{
|
||||
std::cout << std::setw (12) << g_signalDbmAvg <<
|
||||
std::setw (12) << g_noiseDbmAvg <<
|
||||
std::setw (12) << (g_signalDbmAvg - g_noiseDbmAvg) <<
|
||||
std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << std::setw (12) << "N/A" <<
|
||||
std::setw (12) << "N/A" <<
|
||||
std::setw (12) << "N/A" <<
|
||||
std::endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
701
examples/wireless/wifi-spectrum-saturation-example.cc
Normal file
701
examples/wireless/wifi-spectrum-saturation-example.cc
Normal file
@@ -0,0 +1,701 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 MIRKO BANCHI
|
||||
* Copyright (c) 2015 University of Washington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Mirko Banchi <mk.banchi@gmail.com>
|
||||
* Sebastien Deronne <sebastien.deronne@gmail.com>
|
||||
* Tom Henderson <tomhend@u.washington.edu>
|
||||
*
|
||||
* Adapted from ht-wifi-network.cc example
|
||||
*/
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/config-store-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/wifi-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/spectrum-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
|
||||
// This is a simple example of an IEEE 802.11n Wi-Fi network.
|
||||
//
|
||||
// The main use case is to enable and test SpectrumWifiPhy vs YansWifiPhy
|
||||
// under saturation conditions (for max throughput).
|
||||
//
|
||||
// Network topology:
|
||||
//
|
||||
// Wi-Fi 192.168.1.0
|
||||
//
|
||||
// STA AP
|
||||
// * <-- distance --> *
|
||||
// | |
|
||||
// n1 n2
|
||||
//
|
||||
// Users may vary the following command-line arguments in addition to the
|
||||
// attributes, global values, and default values typically available:
|
||||
//
|
||||
// --simulationTime: Simulation time in seconds [10]
|
||||
// --distance: meters separation between nodes [50]
|
||||
// --index: restrict index to single value between 0 and 31 [256]
|
||||
// --wifiType: select ns3::SpectrumWifiPhy or ns3::YansWifiPhy [ns3::SpectrumWifiPhy]
|
||||
// --errorModelType: select ns3::NistErrorRateModel or ns3::YansErrorRateModel [ns3::NistErrorRateModel]
|
||||
// --enablePcap: enable pcap output [false]
|
||||
//
|
||||
// By default, the program will step through 64 index values, corresponding
|
||||
// to the following MCS, channel width, and guard interval combinations:
|
||||
// index 0-7: MCS 0-7, long guard interval, 20 MHz channel
|
||||
// index 8-15: MCS 0-7, short guard interval, 20 MHz channel
|
||||
// index 16-23: MCS 0-7, long guard interval, 40 MHz channel
|
||||
// index 24-31: MCS 0-7, short guard interval, 40 MHz channel
|
||||
// index 32-39: MCS 8-15, long guard interval, 20 MHz channel
|
||||
// index 40-47: MCS 8-15, short guard interval, 20 MHz channel
|
||||
// index 48-55: MCS 8-15, long guard interval, 40 MHz channel
|
||||
// index 56-63: MCS 8-15, short guard interval, 40 MHz channel
|
||||
// and send packets at a high rate using each MCS, using the SpectrumWifiPhy
|
||||
// and the NistErrorRateModel, at a distance of 1 meter. The program outputs
|
||||
// results such as:
|
||||
//
|
||||
// wifiType: ns3::SpectrumWifiPhy distance: 1m
|
||||
// index MCS width Rate (Mb/s) Tput (Mb/s) Received
|
||||
// 0 0 20 6.5 5.96219 5063
|
||||
// 1 1 20 13 11.9491 10147
|
||||
// 2 2 20 19.5 17.9184 15216
|
||||
// 3 3 20 26 23.9253 20317
|
||||
// ...
|
||||
//
|
||||
// selection of index values 32-63 will result in MCS selection 8-15
|
||||
// involving two spatial streams
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("WifiSpectrumSaturationExample");
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
double distance = 1;
|
||||
double simulationTime = 10; //seconds
|
||||
uint16_t index = 256;
|
||||
uint32_t channelWidth;
|
||||
std::string wifiType = "ns3::SpectrumWifiPhy";
|
||||
std::string errorModelType = "ns3::NistErrorRateModel";
|
||||
bool enablePcap = false;
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime);
|
||||
cmd.AddValue ("distance", "meters separation between nodes", distance);
|
||||
cmd.AddValue ("index", "restrict index to single value between 0 and 63", index);
|
||||
cmd.AddValue ("wifiType", "select ns3::SpectrumWifiPhy or ns3::YansWifiPhy", wifiType);
|
||||
cmd.AddValue ("errorModelType", "select ns3::NistErrorRateModel or ns3::YansErrorRateModel", errorModelType);
|
||||
cmd.AddValue ("enablePcap", "enable pcap output", enablePcap);
|
||||
cmd.Parse (argc,argv);
|
||||
|
||||
uint16_t startIndex = 0;
|
||||
uint16_t stopIndex = 63;
|
||||
if (index < 64)
|
||||
{
|
||||
startIndex = index;
|
||||
stopIndex = index;
|
||||
}
|
||||
|
||||
std::cout << "wifiType: " << wifiType << " distance: " << distance << "m" << std::endl;
|
||||
std::cout << std::setw (5) << "index" <<
|
||||
std::setw (6) << "MCS" <<
|
||||
std::setw (8) << "width" <<
|
||||
std::setw (12) << "Rate (Mb/s)" <<
|
||||
std::setw (12) << "Tput (Mb/s)" <<
|
||||
std::setw (10) << "Received " <<
|
||||
std::endl;
|
||||
for (uint16_t i = startIndex; i <= stopIndex; i++)
|
||||
{
|
||||
uint32_t payloadSize;
|
||||
payloadSize = 1472; // 1500 bytes IPv4
|
||||
|
||||
NodeContainer wifiStaNode;
|
||||
wifiStaNode.Create (1);
|
||||
NodeContainer wifiApNode;
|
||||
wifiApNode.Create (1);
|
||||
|
||||
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
|
||||
SpectrumWifiPhyHelper spectrumPhy = SpectrumWifiPhyHelper::Default ();
|
||||
if (wifiType == "ns3::YansWifiPhy")
|
||||
{
|
||||
YansWifiChannelHelper channel;
|
||||
channel.AddPropagationLoss ("ns3::FriisPropagationLossModel");
|
||||
channel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
|
||||
phy.SetChannel (channel.Create ());
|
||||
phy.Set ("TxPowerStart", DoubleValue (1));
|
||||
phy.Set ("TxPowerEnd", DoubleValue (1));
|
||||
|
||||
if (i <= 7)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
channelWidth = 20;
|
||||
}
|
||||
else if (i > 7 && i <= 15)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
channelWidth = 20;
|
||||
}
|
||||
else if (i > 15 && i <= 23)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
channelWidth = 40;
|
||||
}
|
||||
else if (i > 23 && i <= 31)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
channelWidth = 40;
|
||||
}
|
||||
else if (i > 31 && i <= 39)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
phy.Set ("RxAntennas", UintegerValue (2));
|
||||
phy.Set ("TxAntennas", UintegerValue (2));
|
||||
channelWidth = 20;
|
||||
}
|
||||
else if (i > 39 && i <= 47)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
phy.Set ("RxAntennas", UintegerValue (2));
|
||||
phy.Set ("TxAntennas", UintegerValue (2));
|
||||
channelWidth = 20;
|
||||
}
|
||||
else if (i > 47 && i <= 55)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
phy.Set ("RxAntennas", UintegerValue (2));
|
||||
phy.Set ("TxAntennas", UintegerValue (2));
|
||||
channelWidth = 40;
|
||||
}
|
||||
else if (i > 55 && i <= 63)
|
||||
{
|
||||
phy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
phy.Set ("RxAntennas", UintegerValue (2));
|
||||
phy.Set ("TxAntennas", UintegerValue (2));
|
||||
channelWidth = 40;
|
||||
}
|
||||
}
|
||||
else if (wifiType == "ns3::SpectrumWifiPhy")
|
||||
{
|
||||
Ptr<SingleModelSpectrumChannel> spectrumChannel
|
||||
= CreateObject<SingleModelSpectrumChannel> ();
|
||||
Ptr<FriisPropagationLossModel> lossModel
|
||||
= CreateObject<FriisPropagationLossModel> ();
|
||||
spectrumChannel->AddPropagationLossModel (lossModel);
|
||||
|
||||
Ptr<ConstantSpeedPropagationDelayModel> delayModel
|
||||
= CreateObject<ConstantSpeedPropagationDelayModel> ();
|
||||
spectrumChannel->SetPropagationDelayModel (delayModel);
|
||||
|
||||
spectrumPhy.SetChannel (spectrumChannel);
|
||||
spectrumPhy.SetErrorRateModel (errorModelType);
|
||||
spectrumPhy.Set ("Frequency", UintegerValue (5180)); // channel 36 at 20 MHz
|
||||
spectrumPhy.Set ("TxPowerStart", DoubleValue (1));
|
||||
spectrumPhy.Set ("TxPowerEnd", DoubleValue (1));
|
||||
|
||||
if (i <= 7)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
channelWidth = 20;
|
||||
}
|
||||
else if (i > 7 && i <= 15)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
channelWidth = 20;
|
||||
}
|
||||
else if (i > 15 && i <= 23)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
channelWidth = 40;
|
||||
}
|
||||
else if (i > 23 && i <= 31)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
channelWidth = 40;
|
||||
}
|
||||
else if (i > 31 && i <= 39)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
spectrumPhy.Set ("RxAntennas", UintegerValue (2));
|
||||
spectrumPhy.Set ("TxAntennas", UintegerValue (2));
|
||||
channelWidth = 20;
|
||||
}
|
||||
else if (i > 39 && i <= 47)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
spectrumPhy.Set ("RxAntennas", UintegerValue (2));
|
||||
spectrumPhy.Set ("TxAntennas", UintegerValue (2));
|
||||
channelWidth = 20;
|
||||
}
|
||||
else if (i > 47 && i <= 55)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (false));
|
||||
spectrumPhy.Set ("RxAntennas", UintegerValue (2));
|
||||
spectrumPhy.Set ("TxAntennas", UintegerValue (2));
|
||||
channelWidth = 40;
|
||||
}
|
||||
else if (i > 55 && i <= 63)
|
||||
{
|
||||
spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (true));
|
||||
spectrumPhy.Set ("RxAntennas", UintegerValue (2));
|
||||
spectrumPhy.Set ("TxAntennas", UintegerValue (2));
|
||||
channelWidth = 40;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unsupported WiFi type " << wifiType);
|
||||
}
|
||||
|
||||
|
||||
WifiHelper wifi;
|
||||
wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
|
||||
WifiMacHelper mac;
|
||||
|
||||
Ssid ssid = Ssid ("ns380211n");
|
||||
|
||||
double datarate = 0;
|
||||
StringValue DataRate;
|
||||
if (i == 0)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 6.5;
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 13;
|
||||
}
|
||||
else if (i == 2)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 19.5;
|
||||
}
|
||||
else if (i == 3)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 26;
|
||||
}
|
||||
else if (i == 4)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 39;
|
||||
}
|
||||
else if (i == 5)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 52;
|
||||
}
|
||||
else if (i == 6)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 58.5;
|
||||
}
|
||||
else if (i == 7)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 65;
|
||||
}
|
||||
else if (i == 8)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 7.2;
|
||||
}
|
||||
else if (i == 9)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 14.4;
|
||||
}
|
||||
else if (i == 10)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 21.7;
|
||||
}
|
||||
else if (i == 11)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 28.9;
|
||||
}
|
||||
else if (i == 12)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 43.3;
|
||||
}
|
||||
else if (i == 13)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 57.8;
|
||||
}
|
||||
else if (i == 14)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 65;
|
||||
}
|
||||
else if (i == 15)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 72.2;
|
||||
}
|
||||
else if (i == 16)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 13.5;
|
||||
}
|
||||
else if (i == 17)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 27;
|
||||
}
|
||||
else if (i == 18)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 40.5;
|
||||
}
|
||||
else if (i == 19)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 54;
|
||||
}
|
||||
else if (i == 20)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 81;
|
||||
}
|
||||
else if (i == 21)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 108;
|
||||
}
|
||||
else if (i == 22)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 121.5;
|
||||
}
|
||||
else if (i == 23)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 135;
|
||||
}
|
||||
else if (i == 24)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs0");
|
||||
datarate = 15;
|
||||
}
|
||||
else if (i == 25)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs1");
|
||||
datarate = 30;
|
||||
}
|
||||
else if (i == 26)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs2");
|
||||
datarate = 45;
|
||||
}
|
||||
else if (i == 27)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs3");
|
||||
datarate = 60;
|
||||
}
|
||||
else if (i == 28)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs4");
|
||||
datarate = 90;
|
||||
}
|
||||
else if (i == 29)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs5");
|
||||
datarate = 120;
|
||||
}
|
||||
else if (i == 30)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs6");
|
||||
datarate = 135;
|
||||
}
|
||||
else if (i == 31)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs7");
|
||||
datarate = 150;
|
||||
}
|
||||
else if (i == 32)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs8");
|
||||
datarate = 13;
|
||||
}
|
||||
else if (i == 33)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs9");
|
||||
datarate = 26;
|
||||
}
|
||||
else if (i == 34)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs10");
|
||||
datarate = 39;
|
||||
}
|
||||
else if (i == 35)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs11");
|
||||
datarate = 52;
|
||||
}
|
||||
else if (i == 36)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs12");
|
||||
datarate = 78;
|
||||
}
|
||||
else if (i == 37)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs13");
|
||||
datarate = 104;
|
||||
}
|
||||
else if (i == 38)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs14");
|
||||
datarate = 117;
|
||||
}
|
||||
else if (i == 39)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs15");
|
||||
datarate = 130;
|
||||
}
|
||||
else if (i == 40)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs8");
|
||||
datarate = 14.4;
|
||||
}
|
||||
else if (i == 41)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs9");
|
||||
datarate = 28.9;
|
||||
}
|
||||
else if (i == 42)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs10");
|
||||
datarate = 43.3;
|
||||
}
|
||||
else if (i == 43)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs11");
|
||||
datarate = 57.8;
|
||||
}
|
||||
else if (i == 44)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs12");
|
||||
datarate = 86.7;
|
||||
}
|
||||
else if (i == 45)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs13");
|
||||
datarate = 115.6;
|
||||
}
|
||||
else if (i == 46)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs14");
|
||||
datarate = 130.3;
|
||||
}
|
||||
else if (i == 47)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs15");
|
||||
datarate = 144.4;
|
||||
}
|
||||
else if (i == 48)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs8");
|
||||
datarate = 27;
|
||||
}
|
||||
else if (i == 49)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs9");
|
||||
datarate = 54;
|
||||
}
|
||||
else if (i == 50)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs10");
|
||||
datarate = 81;
|
||||
}
|
||||
else if (i == 51)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs11");
|
||||
datarate = 108;
|
||||
}
|
||||
else if (i == 52)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs12");
|
||||
datarate = 162;
|
||||
}
|
||||
else if (i == 53)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs13");
|
||||
datarate = 216;
|
||||
}
|
||||
else if (i == 54)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs14");
|
||||
datarate = 243;
|
||||
}
|
||||
else if (i == 55)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs15");
|
||||
datarate = 270;
|
||||
}
|
||||
else if (i == 56)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs8");
|
||||
datarate = 30;
|
||||
}
|
||||
else if (i == 57)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs9");
|
||||
datarate = 60;
|
||||
}
|
||||
else if (i == 58)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs10");
|
||||
datarate = 90;
|
||||
}
|
||||
else if (i == 59)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs11");
|
||||
datarate = 120;
|
||||
}
|
||||
else if (i == 60)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs12");
|
||||
datarate = 180;
|
||||
}
|
||||
else if (i == 61)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs13");
|
||||
datarate = 240;
|
||||
}
|
||||
else if (i == 62)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs14");
|
||||
datarate = 270;
|
||||
}
|
||||
else if (i == 63)
|
||||
{
|
||||
DataRate = StringValue ("HtMcs15");
|
||||
datarate = 300;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Illegal index i " << i);
|
||||
}
|
||||
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager","DataMode", DataRate,
|
||||
"ControlMode", DataRate);
|
||||
|
||||
NetDeviceContainer staDevice;
|
||||
NetDeviceContainer apDevice;
|
||||
|
||||
if (wifiType == "ns3::YansWifiPhy")
|
||||
{
|
||||
mac.SetType ("ns3::StaWifiMac",
|
||||
"Ssid", SsidValue (ssid),
|
||||
"ActiveProbing", BooleanValue (false));
|
||||
staDevice = wifi.Install (phy, mac, wifiStaNode);
|
||||
mac.SetType ("ns3::ApWifiMac",
|
||||
"Ssid", SsidValue (ssid));
|
||||
apDevice = wifi.Install (phy, mac, wifiApNode);
|
||||
|
||||
}
|
||||
else if (wifiType == "ns3::SpectrumWifiPhy")
|
||||
{
|
||||
mac.SetType ("ns3::StaWifiMac",
|
||||
"Ssid", SsidValue (ssid),
|
||||
"ActiveProbing", BooleanValue (false));
|
||||
staDevice = wifi.Install (spectrumPhy, mac, wifiStaNode);
|
||||
mac.SetType ("ns3::ApWifiMac",
|
||||
"Ssid", SsidValue (ssid));
|
||||
apDevice = wifi.Install (spectrumPhy, mac, wifiApNode);
|
||||
}
|
||||
|
||||
// Channel width must be set *after* installation because the attribute
|
||||
// is overwritten by the ConfigureStandard method ()
|
||||
Config::Set ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", UintegerValue (channelWidth));
|
||||
|
||||
// mobility.
|
||||
MobilityHelper mobility;
|
||||
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
|
||||
|
||||
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
|
||||
positionAlloc->Add (Vector (distance, 0.0, 0.0));
|
||||
mobility.SetPositionAllocator (positionAlloc);
|
||||
|
||||
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
||||
|
||||
mobility.Install (wifiApNode);
|
||||
mobility.Install (wifiStaNode);
|
||||
|
||||
/* Internet stack*/
|
||||
InternetStackHelper stack;
|
||||
stack.Install (wifiApNode);
|
||||
stack.Install (wifiStaNode);
|
||||
|
||||
Ipv4AddressHelper address;
|
||||
|
||||
address.SetBase ("192.168.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer staNodeInterface;
|
||||
Ipv4InterfaceContainer apNodeInterface;
|
||||
|
||||
staNodeInterface = address.Assign (staDevice);
|
||||
apNodeInterface = address.Assign (apDevice);
|
||||
|
||||
/* Setting applications */
|
||||
ApplicationContainer serverApp, sinkApp;
|
||||
//UDP flow
|
||||
UdpServerHelper myServer (9);
|
||||
serverApp = myServer.Install (wifiStaNode.Get (0));
|
||||
serverApp.Start (Seconds (0.0));
|
||||
serverApp.Stop (Seconds (simulationTime + 1));
|
||||
|
||||
UdpClientHelper myClient (staNodeInterface.GetAddress (0), 9);
|
||||
myClient.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
|
||||
myClient.SetAttribute ("Interval", TimeValue (Time ("0.00002"))); //packets/s
|
||||
myClient.SetAttribute ("PacketSize", UintegerValue (payloadSize));
|
||||
|
||||
ApplicationContainer clientApp = myClient.Install (wifiApNode.Get (0));
|
||||
clientApp.Start (Seconds (1.0));
|
||||
clientApp.Stop (Seconds (simulationTime + 1));
|
||||
|
||||
if (enablePcap)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "wifi-spectrum-saturation-example-" << i;
|
||||
phy.EnablePcap (ss.str (), apDevice);
|
||||
}
|
||||
|
||||
Simulator::Stop (Seconds (simulationTime + 1));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
double throughput;
|
||||
uint32_t totalPacketsThrough;
|
||||
totalPacketsThrough = DynamicCast<UdpServer> (serverApp.Get (0))->GetReceived ();
|
||||
throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); //Mbit/s
|
||||
std::cout << std::setw (5) << i <<
|
||||
std::setw (6) << (i % 8) + 8 * (i / 32) <<
|
||||
std::setw (8) << channelWidth <<
|
||||
std::setw (10) << datarate <<
|
||||
std::setw (12) << throughput <<
|
||||
std::setw (8) << totalPacketsThrough <<
|
||||
std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -91,3 +91,11 @@ def build(bld):
|
||||
obj = bld.create_ns3_program('80211e-txop', ['internet', 'mobility', 'wifi', 'applications'])
|
||||
obj.source = '80211e-txop.cc'
|
||||
|
||||
obj = bld.create_ns3_program('wifi-spectrum-per-example', ['internet', 'mobility', 'wifi', 'applications', 'spectrum'])
|
||||
obj.source = 'wifi-spectrum-per-example.cc'
|
||||
|
||||
obj = bld.create_ns3_program('wifi-spectrum-per-interference', ['internet', 'mobility', 'wifi', 'applications', 'spectrum'])
|
||||
obj.source = 'wifi-spectrum-per-interference.cc'
|
||||
|
||||
obj = bld.create_ns3_program('wifi-spectrum-saturation-example', ['internet', 'mobility', 'wifi', 'applications', 'spectrum'])
|
||||
obj.source = 'wifi-spectrum-saturation-example.cc'
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 CTTC
|
||||
* Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
|
||||
*
|
||||
* 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
|
||||
@@ -16,14 +17,350 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Nicola Baldo <nbaldo@cttc.es>
|
||||
* Giuseppe Piro <g.piro@poliba.it>
|
||||
*/
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <cmath>
|
||||
#include "wifi-spectrum-value-helper.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/fatal-error.h"
|
||||
#include "ns3/assert.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/// The Wi-Fi spectrum model
|
||||
NS_LOG_COMPONENT_DEFINE ("WifiSpectrumValueHelper");
|
||||
|
||||
struct WifiSpectrumModelId
|
||||
{
|
||||
WifiSpectrumModelId (uint32_t f, uint32_t w);
|
||||
uint32_t m_centerFrequency;
|
||||
uint32_t m_channelWidth;
|
||||
};
|
||||
|
||||
WifiSpectrumModelId::WifiSpectrumModelId (uint32_t f, uint32_t w)
|
||||
: m_centerFrequency (f),
|
||||
m_channelWidth (w)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << f << w);
|
||||
}
|
||||
|
||||
bool
|
||||
operator < (const WifiSpectrumModelId& a, const WifiSpectrumModelId& b)
|
||||
{
|
||||
return ( (a.m_centerFrequency < b.m_centerFrequency) || ( (a.m_centerFrequency == b.m_centerFrequency) && (a.m_channelWidth < b.m_channelWidth)));
|
||||
}
|
||||
|
||||
static std::map<WifiSpectrumModelId, Ptr<SpectrumModel> > g_wifiSpectrumModelMap;
|
||||
|
||||
Ptr<SpectrumModel>
|
||||
WifiSpectrumValueHelper::GetSpectrumModel (uint32_t centerFrequency, uint32_t channelWidth)
|
||||
{
|
||||
NS_LOG_FUNCTION (centerFrequency << channelWidth);
|
||||
Ptr<SpectrumModel> ret;
|
||||
WifiSpectrumModelId key (centerFrequency, channelWidth);
|
||||
std::map<WifiSpectrumModelId, Ptr<SpectrumModel> >::iterator it = g_wifiSpectrumModelMap.find (key);
|
||||
if (it != g_wifiSpectrumModelMap.end ())
|
||||
{
|
||||
ret = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
Bands bands;
|
||||
double centerFrequencyHz = centerFrequency * 1e6;
|
||||
// Overall bandwidth will be channelWidth plus 10 MHz guards on each side
|
||||
double bandwidth = (channelWidth + 20) * 1e6;
|
||||
// Use OFDM subcarrier width of 312.5 KHz as band granularity
|
||||
double bandBandwidth = 312500;
|
||||
// For OFDM, the center subcarrier is null (at center frequency)
|
||||
uint32_t numBands = static_cast<uint32_t> (bandwidth / bandBandwidth + 0.5);
|
||||
NS_ASSERT (numBands > 0);
|
||||
if (numBands % 2 == 0)
|
||||
{
|
||||
// round up to the nearest odd number of subbands so that bands
|
||||
// are symmetric around center frequency
|
||||
NS_LOG_DEBUG ("Total bandwidth evenly divided by 312.5 KHz");
|
||||
numBands += 1;
|
||||
}
|
||||
NS_ASSERT_MSG (numBands % 2 == 1, "Number of bands should be odd");
|
||||
// lay down numBands/2 bands symmetrically around center frequency
|
||||
// and place an additional band at center frequency
|
||||
double startingFrequencyHz = centerFrequencyHz - (numBands/2 * bandBandwidth) - bandBandwidth/2;
|
||||
for (size_t i = 0; i < numBands; i++)
|
||||
{
|
||||
BandInfo info;
|
||||
double f = startingFrequencyHz + (i * bandBandwidth);
|
||||
info.fl = f;
|
||||
f += bandBandwidth/2;
|
||||
info.fc = f;
|
||||
f += bandBandwidth/2;
|
||||
info.fh = f;
|
||||
NS_LOG_DEBUG ("creating band " << i << " (" << info.fl << ":" << info.fc << ":" << info.fh << ")");
|
||||
bands.push_back (info);
|
||||
}
|
||||
ret = Create<SpectrumModel> (bands);
|
||||
g_wifiSpectrumModelMap.insert (std::pair<WifiSpectrumModelId, Ptr<SpectrumModel> > (key, ret));
|
||||
}
|
||||
NS_LOG_LOGIC ("returning SpectrumModel::GetUid () == " << ret->GetUid ());
|
||||
return ret;
|
||||
}
|
||||
|
||||
Ptr<SpectrumValue>
|
||||
WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double txPowerW)
|
||||
{
|
||||
NS_LOG_FUNCTION (centerFrequency << channelWidth << txPowerW);
|
||||
Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth));
|
||||
Values::iterator vit = c->ValuesBegin ();
|
||||
Bands::const_iterator bit = c->ConstBandsBegin ();
|
||||
double txPowerPerBand;
|
||||
switch (channelWidth)
|
||||
{
|
||||
case 20:
|
||||
// 56 subcarriers (52 data + 4 pilot)
|
||||
NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 129, "Unexpected number of bands");
|
||||
// skip 32 subbands, then place power in 28 of the next 32 subbands, then
|
||||
// skip the center subband, then place power in 28 of the next 32
|
||||
// subbands, then skip the final 32 subbands.
|
||||
txPowerPerBand = txPowerW / 56;
|
||||
for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
|
||||
{
|
||||
if ((i >=36 && i <=63) || (i >=65 && i <=92))
|
||||
{
|
||||
*vit = txPowerPerBand / (bit->fh - bit->fl);
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("Added signal power to subbands 36-63 and 65-92");
|
||||
NS_LOG_DEBUG ("Integrated power " << Integral (*(GetPointer (c))));
|
||||
NS_ASSERT_MSG (std::abs (txPowerW - Integral (*(GetPointer (c)))) < 1e-6, "Power allocation failed");
|
||||
break;
|
||||
case 40:
|
||||
// 112 subcarriers (104 data + 8 pilot)
|
||||
// possible alternative: 114 subcarriers (108 data + 6 pilot)
|
||||
NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 193, "Unexpected number of bands");
|
||||
txPowerPerBand = txPowerW / 112;
|
||||
for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
|
||||
{
|
||||
if ((i >=36 && i <=63) || (i >=65 && i <=92) || (i >=100 && i<=127) || (i >=129 && i<= 156))
|
||||
{
|
||||
*vit = txPowerPerBand / (bit->fh - bit->fl);
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("Added signal power to subbands 36-63, 65-92, 100-127, and 129-156");
|
||||
NS_LOG_DEBUG ("Integrated power " << Integral (*(GetPointer (c))));
|
||||
NS_ASSERT_MSG (std::abs (txPowerW - Integral (*(GetPointer (c)))) < 1e-6, "Power allocation failed");
|
||||
break;
|
||||
case 80:
|
||||
// 224 subcarriers (208 data + 16 pilot)
|
||||
// possible alternative: 242 subcarriers (234 data + 8 pilot)
|
||||
NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 321, "Unexpected number of bands");
|
||||
txPowerPerBand = txPowerW / 224;
|
||||
for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
|
||||
{
|
||||
if ((i >= 36 && i <= 63) || (i >= 65 && i <= 92) ||
|
||||
(i >= 100 && i <= 127) || (i >= 129 && i <= 156) ||
|
||||
(i >= 164 && i <= 191) || (i >= 193 && i <= 220) ||
|
||||
(i >= 228 && i <= 255) || (i >= 257 && i <= 284))
|
||||
{
|
||||
*vit = txPowerPerBand / (bit->fh - bit->fl);
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("Added signal power to subbands 36-63, 65-92, 100-127, 129-156, 164-191, 193-220, 228-255, 257-284");
|
||||
NS_LOG_DEBUG ("Integrated power " << Integral (*(GetPointer (c))));
|
||||
NS_ASSERT_MSG (std::abs (txPowerW - Integral (*(GetPointer (c)))) < 1e-6, "Power allocation failed");
|
||||
break;
|
||||
case 160:
|
||||
// 448 subcarriers (416 data + 32 pilot) VHT
|
||||
// possible alternative: 484 subcarriers (468 data + 16 pilot)
|
||||
NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 577, "Unexpected number of bands");
|
||||
txPowerPerBand = txPowerW / 448;
|
||||
for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
|
||||
{
|
||||
if ((i >= 36 && i <= 63) || (i >= 65 && i <= 92) ||
|
||||
(i >= 100 && i <= 127) || (i >= 129 && i <= 156) ||
|
||||
(i >= 164 && i <= 191) || (i >= 193 && i <= 220) ||
|
||||
(i >= 228 && i <= 255) || (i >= 257 && i <= 284) ||
|
||||
(i >= 292 && i <= 319) || (i >= 321 && i <= 348) ||
|
||||
(i >= 356 && i <= 383) || (i >= 385 && i <= 412) ||
|
||||
(i >= 420 && i <= 447) || (i >= 449 && i <= 476) ||
|
||||
(i >= 484 && i <= 511) || (i >= 513 && i <= 540))
|
||||
{
|
||||
*vit = txPowerPerBand / (bit->fh - bit->fl);
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("Added signal power to subbands 36-63, 65-92, 100-127, 129-156, 164-191, 193-220, 228-255, 257-284, 292-319, 321-348, 356-383, 385-412, 420-447, 449-476, 484-511, and 513-540");
|
||||
NS_LOG_DEBUG ("Integrated power " << Integral (*(GetPointer (c))));
|
||||
NS_ASSERT_MSG (std::abs (txPowerW - Integral (*(GetPointer (c)))) < 1e-6, "Power allocation failed");
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("ChannelWidth " << channelWidth << " unsupported");
|
||||
break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
Ptr<SpectrumValue>
|
||||
WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double txPowerW)
|
||||
{
|
||||
NS_LOG_FUNCTION (centerFrequency << channelWidth << txPowerW);
|
||||
Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth));
|
||||
Values::iterator vit = c->ValuesBegin ();
|
||||
Bands::const_iterator bit = c->ConstBandsBegin ();
|
||||
double txPowerPerBand;
|
||||
switch (channelWidth)
|
||||
{
|
||||
case 20:
|
||||
// 52 subcarriers (48 data + 4 pilot)
|
||||
// skip 38 subbands, then place power in 26 subbands, then
|
||||
// skip the center subband, then place power in 26 subbands, then skip
|
||||
// the final 38 subbands.
|
||||
std::cout << c->GetSpectrumModel ()->GetNumBands () << std::endl;
|
||||
NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 129, "Unexpected number of bands");
|
||||
txPowerPerBand = txPowerW / 52;
|
||||
for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
|
||||
{
|
||||
if ((i >=38 && i <=63) || (i >=65 && i <=90))
|
||||
{
|
||||
*vit = txPowerPerBand / (bit->fh - bit->fl);
|
||||
}
|
||||
else
|
||||
{
|
||||
*vit = 0;
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("Added signal power to subbands 38-63 and 65-90");
|
||||
NS_LOG_DEBUG ("Integrated power " << Integral (*(GetPointer (c))));
|
||||
NS_ASSERT_MSG (std::abs (txPowerW - Integral (*(GetPointer (c)))) < 1e-6, "Power allocation failed");
|
||||
break;
|
||||
case 10:
|
||||
// 28 subcarriers (24 data + 4 pilot)
|
||||
// skip 34 subbands, then place power in 14 subbands, then
|
||||
// skip the center subband, then place power in 14 subbands, then skip
|
||||
// the final 34 subbands.
|
||||
std::cout << c->GetSpectrumModel ()->GetNumBands () << std::endl;
|
||||
NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 97, "Unexpected number of bands");
|
||||
txPowerPerBand = txPowerW / 28;
|
||||
for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
|
||||
{
|
||||
if ((i >=34 && i <=47) || (i >=49 && i <=62))
|
||||
{
|
||||
*vit = txPowerPerBand / (bit->fh - bit->fl);
|
||||
}
|
||||
else
|
||||
{
|
||||
*vit = 0;
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("Added signal power to subbands 34-47 and 49-62");
|
||||
NS_LOG_DEBUG ("Integrated power " << Integral (*(GetPointer (c))));
|
||||
NS_ASSERT_MSG (std::abs (txPowerW - Integral (*(GetPointer (c)))) < 1e-6, "Power allocation failed");
|
||||
break;
|
||||
case 5:
|
||||
// 16 subcarriers (12 data + 4 pilot)
|
||||
// skip 34 subbands, then place power in 14 subbands, then
|
||||
// skip the center subband, then place power in 14 subbands, then skip
|
||||
// the final 34 subbands.
|
||||
std::cout << c->GetSpectrumModel ()->GetNumBands () << std::endl;
|
||||
NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == 81, "Unexpected number of bands");
|
||||
txPowerPerBand = txPowerW / 16;
|
||||
for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
|
||||
{
|
||||
if ((i >=32 && i <=39) || (i >=41 && i <=48))
|
||||
{
|
||||
*vit = txPowerPerBand / (bit->fh - bit->fl);
|
||||
}
|
||||
else
|
||||
{
|
||||
*vit = 0;
|
||||
}
|
||||
}
|
||||
NS_LOG_DEBUG ("Added signal power to subbands 32-39 and 41-48");
|
||||
NS_LOG_DEBUG ("Integrated power " << Integral (*(GetPointer (c))));
|
||||
NS_ASSERT_MSG (std::abs (txPowerW - Integral (*(GetPointer (c)))) < 1e-6, "Power allocation failed");
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("ChannelWidth " << channelWidth << " unsupported");
|
||||
break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// Power allocated to 71 center subbands out of 135 total subbands in the band
|
||||
Ptr<SpectrumValue>
|
||||
WifiSpectrumValueHelper::CreateDsssTxPowerSpectralDensity (uint32_t centerFrequency, double txPowerW)
|
||||
{
|
||||
NS_LOG_FUNCTION (centerFrequency << txPowerW);
|
||||
uint32_t channelWidth = 22; // DSSS channels are 22 MHz wide
|
||||
Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth));
|
||||
Values::iterator vit = c->ValuesBegin ();
|
||||
Bands::const_iterator bit = c->ConstBandsBegin ();
|
||||
double txPowerPerBand;
|
||||
// Evenly spread power across 22 MHz (71 bands)
|
||||
NS_ASSERT (c->GetSpectrumModel ()->GetNumBands () == 135);
|
||||
txPowerPerBand = txPowerW / 71;
|
||||
for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
|
||||
{
|
||||
if (i >=32 && i <=102)
|
||||
{
|
||||
*vit = txPowerPerBand / (bit->fh - bit->fl);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
Ptr<SpectrumValue>
|
||||
WifiSpectrumValueHelper::CreateNoisePowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double noiseFigure)
|
||||
{
|
||||
Ptr<SpectrumModel> model = GetSpectrumModel (centerFrequency, channelWidth);
|
||||
return CreateNoisePowerSpectralDensity (noiseFigure, model);
|
||||
}
|
||||
|
||||
Ptr<SpectrumValue>
|
||||
WifiSpectrumValueHelper::CreateNoisePowerSpectralDensity (double noiseFigureDb, Ptr<SpectrumModel> spectrumModel)
|
||||
{
|
||||
NS_LOG_FUNCTION (noiseFigureDb << spectrumModel);
|
||||
|
||||
// see "LTE - From theory to practice"
|
||||
// Section 22.4.4.2 Thermal Noise and Receiver Noise Figure
|
||||
const double kT_dBm_Hz = -174.0; // dBm/Hz
|
||||
double kT_W_Hz = std::pow (10.0, (kT_dBm_Hz - 30) / 10.0);
|
||||
double noiseFigureLinear = std::pow (10.0, noiseFigureDb / 10.0);
|
||||
double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
|
||||
|
||||
Ptr<SpectrumValue> noisePsd = Create <SpectrumValue> (spectrumModel);
|
||||
(*noisePsd) = noisePowerSpectralDensity;
|
||||
NS_LOG_DEBUG ("NoisePowerSpectralDensity has integrated power of " << Integral (*(GetPointer (noisePsd))));
|
||||
return noisePsd;
|
||||
}
|
||||
|
||||
Ptr<SpectrumValue>
|
||||
WifiSpectrumValueHelper::CreateRfFilter (uint32_t centerFrequency, uint32_t channelWidth)
|
||||
{
|
||||
NS_LOG_FUNCTION (centerFrequency << channelWidth);
|
||||
Ptr<SpectrumValue> c = Create <SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth));
|
||||
size_t numBands = c->GetSpectrumModel ()->GetNumBands ();
|
||||
Bands::const_iterator bit = c->ConstBandsBegin ();
|
||||
Values::iterator vit = c->ValuesBegin ();
|
||||
uint32_t bandBandwidth = static_cast<uint32_t> (((bit->fh - bit->fl) + 0.5));
|
||||
NS_LOG_DEBUG ("Band bandwidth: " << bandBandwidth);
|
||||
size_t numBandsInFilter = static_cast<size_t> (channelWidth * 1e6 / bandBandwidth);
|
||||
if (channelWidth % bandBandwidth != 0)
|
||||
{
|
||||
numBandsInFilter += 1;
|
||||
}
|
||||
NS_LOG_DEBUG ("Num bands in filter: " << numBandsInFilter);
|
||||
// Set the value of the filter to 1 for the center-most numBandsInFilter
|
||||
NS_ASSERT_MSG ((numBandsInFilter % 2 == 1) && (numBands % 2 == 1), "Should have odd number of bands");
|
||||
size_t startIndex = (numBands - numBandsInFilter) / 2;
|
||||
vit += startIndex;
|
||||
bit += startIndex;
|
||||
for (size_t i = startIndex; i < startIndex + numBandsInFilter; i++, vit++, bit++)
|
||||
{
|
||||
*vit = 1;
|
||||
}
|
||||
NS_LOG_DEBUG ("Added subbands " << startIndex << " to " << startIndex + numBandsInFilter << " to filter");
|
||||
return c;
|
||||
}
|
||||
|
||||
static Ptr<SpectrumModel> g_WifiSpectrumModel5Mhz;
|
||||
|
||||
WifiSpectrumValueHelper::~WifiSpectrumValueHelper ()
|
||||
@@ -35,7 +372,7 @@ WifiSpectrumValue5MhzFactory::~WifiSpectrumValue5MhzFactory ()
|
||||
}
|
||||
|
||||
/**
|
||||
* Static class to initialize the values for the Wi-Fi spectrum model
|
||||
* Static class to initialize the values for the 2.4 GHz Wi-Fi spectrum model
|
||||
*/
|
||||
static class WifiSpectrumModel5MhzInitializer
|
||||
{
|
||||
|
||||
@@ -26,77 +26,144 @@
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup spectrum
|
||||
*
|
||||
* This abstract class defines the interface for interacting with all WifiSpectrumValue implementations.
|
||||
*
|
||||
* This class defines all functions to create a spectrum model for
|
||||
* Wi-Fi based on a a spectral model aligned with an OFDM subcarrier
|
||||
* spacing of 312.5 KHz (model also reused for DSSS modulations)
|
||||
*/
|
||||
class WifiSpectrumValueHelper
|
||||
{
|
||||
public:
|
||||
virtual ~WifiSpectrumValueHelper ();
|
||||
/**
|
||||
* Creates a SpectrumValue instance which
|
||||
* has a constant value for all frequencies
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~WifiSpectrumValueHelper ();
|
||||
|
||||
/**
|
||||
* Return a SpectrumModel instance corresponding to the center frequency
|
||||
* and channel width. The model includes +/- 10 MHz of guard bands
|
||||
* (i.e. the model will span (channelWidth + 20) MHz of bandwidth).
|
||||
*
|
||||
* \param centerFrequency center frequency (MHz)
|
||||
* \param channelWidth channel width (MHz)
|
||||
* \return the static SpectrumModel instance corresponding to the
|
||||
* given carrier frequency and channel width configuration.
|
||||
*/
|
||||
static Ptr<SpectrumModel> GetSpectrumModel (uint32_t centerFrequency, uint32_t channelWidth);
|
||||
|
||||
/**
|
||||
* Create a transmit power spectral density corresponding to OFDM
|
||||
* High Throughput (HT) (802.11n/ac). Channel width may vary between
|
||||
* 20, 40, 80, and 160 MHz.
|
||||
*
|
||||
* \param centerFrequency center frequency (MHz)
|
||||
* \param channelWidth channel width (MHz)
|
||||
* \param txPowerW transmit power (W) to allocate
|
||||
*/
|
||||
static Ptr<SpectrumValue> CreateHtOfdmTxPowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double txPowerW);
|
||||
|
||||
/**
|
||||
* Create a transmit power spectral density corresponding to OFDM
|
||||
* (802.11a/g). Channel width may vary between 20, 10, and 5 MHz.
|
||||
*
|
||||
* \param centerFrequency center frequency (MHz)
|
||||
* \param channelWidth channel width (MHz)
|
||||
* \param txPowerW transmit power (W) to allocate
|
||||
*/
|
||||
static Ptr<SpectrumValue> CreateOfdmTxPowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double txPowerW);
|
||||
|
||||
/**
|
||||
* Create a transmit power spectral density corresponding to DSSS
|
||||
*
|
||||
* The center frequency typically corresponds to 802.11b channel
|
||||
* center frequencies but is not restricted to those frequencies.
|
||||
*
|
||||
* \param centerFrequency center frequency (MHz)
|
||||
* \param txPowerW transmit power (W) to allocate
|
||||
*/
|
||||
static Ptr<SpectrumValue> CreateDsssTxPowerSpectralDensity (uint32_t centerFrequency, double txPowerW);
|
||||
|
||||
/**
|
||||
*
|
||||
* \param centerFrequency center frequency (MHz)
|
||||
* \param channelWidth channel width (MHz)
|
||||
* \param noiseFigure the noise figure in dB w.r.t. a reference temperature of 290K
|
||||
* \return a pointer to a newly allocated SpectrumValue representing the noise Power Spectral Density in W/Hz for each Band
|
||||
*/
|
||||
static Ptr<SpectrumValue> CreateNoisePowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double noiseFigure);
|
||||
|
||||
/**
|
||||
* \param centerFrequency center frequency (MHz)
|
||||
* \param channelWidth channel width (MHz)
|
||||
* \return a pointer to a newly allocated SpectrumValue representing the noise Power Spectral Density in W/Hz corresponding to thermal noise, for each Band
|
||||
*/
|
||||
static Ptr<SpectrumValue> CreateNoisePowerSpectralDensity (double noiseFigure, Ptr<SpectrumModel> spectrumModel);
|
||||
|
||||
/**
|
||||
* \param centerFrequency center frequency (MHz)
|
||||
* \param channelWidth channel width (MHz)
|
||||
* \return a pointer to a SpectrumValue representing the RF filter applied
|
||||
* to an received power spectral density
|
||||
*/
|
||||
static Ptr<SpectrumValue> CreateRfFilter (uint32_t centerFrequency, uint32_t channelWidth);
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup spectrum
|
||||
*
|
||||
* Implements Wifi SpectrumValue for the 2.4 GHz ISM band only, with a
|
||||
* 5 MHz spectrum resolution.
|
||||
*
|
||||
*/
|
||||
class WifiSpectrumValue5MhzFactory
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~WifiSpectrumValue5MhzFactory ();
|
||||
/**
|
||||
* Creates a SpectrumValue instance with a constant value for all frequencies
|
||||
*
|
||||
* @param psd the constant value
|
||||
*
|
||||
* @return a Ptr to a newly created SpectrumValue
|
||||
*/
|
||||
virtual Ptr<SpectrumValue> CreateConstant (double psd) = 0;
|
||||
|
||||
virtual Ptr<SpectrumValue> CreateConstant (double psd);
|
||||
/**
|
||||
* Creates a SpectrumValue instance which
|
||||
* represents the TX Power Spectral Density of a wifi device
|
||||
* corresponding to the provided parameters
|
||||
* Creates a SpectrumValue instance that represents the TX Power Spectral
|
||||
* Density of a wifi device corresponding to the provided parameters
|
||||
*
|
||||
* Since the spectrum model has a resolution of 5 MHz, we model
|
||||
* the transmitted signal with a constant density over a 20MHz
|
||||
* bandwidth centered on the center frequency of the channel. The
|
||||
* transmission power outside the transmission power density is
|
||||
* calculated considering the transmit spectrum mask, see IEEE
|
||||
* Std. 802.11-2007, Annex I. The two bands just outside of the main
|
||||
* 20 MHz are allocated power at -28 dB down from the center 20 MHz,
|
||||
* and the two bands outside of this are allocated power at -40 dB down
|
||||
* (with a total bandwidth of 60 MHz containing non-zero power allocation).
|
||||
*
|
||||
* @param txPower the total TX power in W
|
||||
* @param channel the number of the channel
|
||||
* @param channel the number of the channel (1 <= channel <= 13)
|
||||
*
|
||||
* @return a Ptr to a newly created SpectrumValue
|
||||
*/
|
||||
virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity (double txPower, uint32_t channel) = 0;
|
||||
|
||||
virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity (double txPower, uint32_t channel);
|
||||
/**
|
||||
* Creates a pectrumValue instance which
|
||||
* Creates a SpectrumValue instance which
|
||||
* represents the frequency response of the RF filter which is used
|
||||
* by a wifi device to receive signals when tuned to a particular channel
|
||||
*
|
||||
* @param channel the number of the channel
|
||||
* @param channel the number of the channel (1 <= channel <= 13)
|
||||
*
|
||||
* @return a Ptr to a newly created SpectrumValue
|
||||
*/
|
||||
virtual Ptr<SpectrumValue> CreateRfFilter (uint32_t channel) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup spectrum
|
||||
*
|
||||
* Implements WifiSpectrumValue for the 2.4 GHz ISM band only, with a
|
||||
* 5 MHz spectrum resolution.
|
||||
*
|
||||
*/
|
||||
class WifiSpectrumValue5MhzFactory : public WifiSpectrumValueHelper
|
||||
{
|
||||
public:
|
||||
virtual ~WifiSpectrumValue5MhzFactory ();
|
||||
// inherited from WifiSpectrumValueHelper
|
||||
virtual Ptr<SpectrumValue> CreateConstant (double psd);
|
||||
virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity (double txPower, uint32_t channel);
|
||||
virtual Ptr<SpectrumValue> CreateRfFilter (uint32_t channel);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
|
||||
|
||||
#endif /* WIFI_SPECTRUM_VALUE_HELPER_H */
|
||||
|
||||
@@ -36,9 +36,10 @@ packet-level abstraction of the PHY-level for different PHYs, corresponding to
|
||||
802.11a/b/e/g/n/ac specifications.
|
||||
|
||||
In |ns3|, nodes can have multiple WifiNetDevices on separate channels, and the
|
||||
WifiNetDevice can coexist with other device types; this removes an architectural
|
||||
limitation found in |ns2|. Presently, however, there is no model for
|
||||
cross-channel interference or coupling between channels.
|
||||
WifiNetDevice can coexist with other device types.
|
||||
With the use of the **SpectrumWifiPhy** framework, one can also build scenarios
|
||||
involving cross-channel interference or multiple wireless technologies on
|
||||
a single channel.
|
||||
|
||||
The source code for the WifiNetDevice and its models lives in the directory
|
||||
``src/wifi``.
|
||||
@@ -115,14 +116,9 @@ The **MAC low layer** is split into three main components:
|
||||
PHY layer models
|
||||
================
|
||||
|
||||
The PHY layer implements a single model in the ``ns3::WifiPhy`` class: the
|
||||
physical layer model implemented there is described in a paper entitled
|
||||
`Yet Another Network Simulator <http://cutebugs.net/files/wns2-yans.pdf>`_
|
||||
The acronym *Yans* derives from this paper title.
|
||||
|
||||
In short, the physical layer models are mainly responsible for modeling
|
||||
the reception of packets and for tracking energy consumption. There
|
||||
are typically three main components to this:
|
||||
are typically three main components to packet reception:
|
||||
|
||||
* each packet received is probabilistically evaluated for successful or
|
||||
failed reception. The probability depends on the modulation, on
|
||||
@@ -135,6 +131,17 @@ are typically three main components to this:
|
||||
* one or more error models corresponding to the modulation and standard
|
||||
are used to look up probability of successful reception.
|
||||
|
||||
|ns3| offers users a choice between two physical layer models, with a
|
||||
base interface defined in the ``ns3::WifiPhy`` class. The YansWifiPhy
|
||||
class has been the only physical layer model until recently; the model
|
||||
implemented there is described in a paper entitled
|
||||
`Yet Another Network Simulator <http://cutebugs.net/files/wns2-yans.pdf>`_
|
||||
The acronym *Yans* derives from this paper title. The SpectrumWifiPhy
|
||||
class is an alternative implementation based on the Spectrum framework
|
||||
used for other |ns3| wireless models. Spectrum allows a fine-grained
|
||||
frequency decomposition of the signal, and permits scenarios to
|
||||
include multiple technologies coexisting on the same channel.
|
||||
|
||||
Scope and Limitations
|
||||
*********************
|
||||
|
||||
@@ -145,9 +152,8 @@ attempts to summarize compliance with the standard and with behavior
|
||||
found in practice.
|
||||
|
||||
The physical layer and channel models operate on a per-packet basis, with
|
||||
no frequency-selective propagation or interference effects. Detailed
|
||||
link simulations are not performed, nor are frequency-selective fading
|
||||
or interference models available. Directional antennas are also not
|
||||
no frequency-selective propagation or interference effects when using
|
||||
the default YansWifiPhy model. Directional antennas are also not
|
||||
supported at this time. For additive white gaussian noise (AWGN)
|
||||
scenarios, or wideband interference scenarios, performance is governed
|
||||
by the application of analytical models (based on modulation and factors
|
||||
@@ -186,14 +192,29 @@ We organize these more detailed sections from the bottom-up, in terms of
|
||||
layering, by describing the channel and PHY models first, followed by
|
||||
the MAC models.
|
||||
|
||||
We focus first on the choice between physical layer frameworks. |ns3|
|
||||
contains support for a Wi-Fi-only physical layer model called YansWifiPhy
|
||||
that offers no frequency-level decomposition of the signal. For simulations
|
||||
that involve only Wi-Fi signals on the Wi-Fi channel, and that do not
|
||||
involve frequency-dependent propagation loss or fading models, the default
|
||||
YansWifiPhy framework is a suitable choice. For simulations involving
|
||||
mixed technologies on the same channel, or frequency dependent effects,
|
||||
the SpectrumWifiPhy is more appropriate. The two frameworks are very
|
||||
similarly configured.
|
||||
|
||||
The YansWifiPhy framework uses the ``WifiChannel`` and ``YansWifiChannel``
|
||||
frameworks. The SpectrumWifiPhy framework uses the ``Spectrum`` channel
|
||||
framework, which is not documented herein but in the Spectrum module
|
||||
documentation.
|
||||
|
||||
WifiChannel
|
||||
===========
|
||||
|
||||
``ns3::WifiChannel`` is an abstract base class that allows different channel
|
||||
implementations to be connected. At present, there is only one such channel
|
||||
(the ``ns3::YansWifiChannel``). The class works in tandem with the
|
||||
``ns3::WifiPhy`` class; if you want to provide a new physical layer model,
|
||||
you must subclass both ``ns3::WifiChannel`` and ``ns3::WifiPhy``.
|
||||
(the ``ns3::YansWifiChannel``) since the SpectrumWifiPhy uses the
|
||||
base class ``ns3::SpectrumChannel``. The class works in tandem with the
|
||||
``ns3::WifiPhy`` class.
|
||||
|
||||
The WifiChannel model exists to interconnect WifiPhy objects so that packets
|
||||
sent by one Phy are received by some or all other Phys on the channel.
|
||||
@@ -226,7 +247,7 @@ WifiPhy and related models
|
||||
|
||||
The ``ns3::WifiPhy`` is an abstract base class representing the 802.11
|
||||
physical layer functions. Packets passed to this object (via a
|
||||
``SendPacket()`` method are sent over the ``WifiChannel`` object, and
|
||||
``SendPacket()`` method are sent over a channel object, and
|
||||
upon reception, the receiving PHY object decides (based on signal power
|
||||
and interference) whether the packet was successful or not. This class
|
||||
also provides a number of callbacks for notifications of physical layer
|
||||
@@ -235,8 +256,9 @@ MAC-level processes such as carrier sense, and handles sleep/wake models
|
||||
and energy consumption. The ``ns3::WifiPhy`` hooks to the ``ns3::MacLow``
|
||||
object in the WifiNetDevice.
|
||||
|
||||
There is currently one implementation of the ``WifiPhy``, which is the
|
||||
``ns3::YansWifiPhy``. It works in conjunction with three other objects:
|
||||
There are currently two implementations of the ``WifiPhy``: the
|
||||
``ns3::YansWifiPhy`` and the ``ns3::SpectrumWifiPhy``. They each work in
|
||||
conjunction with three other objects:
|
||||
|
||||
* **WifiPhyStateHelper**: Maintains the PHY state machine
|
||||
* **InterferenceHelper**: Tracks all packets observed on the channel
|
||||
@@ -396,6 +418,70 @@ As a result, there are three error models:
|
||||
Users should select either Nist or Yans models for OFDM (Nist is default),
|
||||
and Dsss will be used in either case for 802.11b.
|
||||
|
||||
SpectrumWifiPhy
|
||||
###############
|
||||
|
||||
This section describes the implementation of the ``SpectrumWifiPhy``
|
||||
class that can be found in ``src/wifi/model/spectrum-wifi-phy.{cc,h}``.
|
||||
|
||||
The implementation also makes use of additional classes found in the
|
||||
same directory:
|
||||
|
||||
* ``wifi-spectrum-phy-interface.{cc,h}``
|
||||
* ``wifi-spectrum-signal-parameters.{cc,h}``
|
||||
|
||||
and classes found in the spectrum module:
|
||||
|
||||
* ``wifi-spectrum-value-helper.{cc,h}``
|
||||
|
||||
The current ``SpectrumWifiPhy`` class
|
||||
reuses the existing interference manager and error rate models originally
|
||||
built for YansWifiPhy, but allows, as a first step, foreign (non Wi-Fi)
|
||||
signals to be treated as additive noise.
|
||||
|
||||
Two main changes were needed to adapt the Spectrum framework to Wi-Fi.
|
||||
First, the physical layer must send signals compatible with the
|
||||
Spectrum channel framework, and in particular, the
|
||||
``MultiModelSpectrumChannel`` that allows signals from different
|
||||
technologies to coexist. Second, the InterferenceHelper must be
|
||||
extended to support the insertion of non-Wi-Fi signals and to
|
||||
add their received power to the noise, in the same way that
|
||||
unintended Wi-Fi signals (perhaps from a different SSID or arriving
|
||||
late from a hidden node) are added to the noise.
|
||||
|
||||
Third, the default value for CcaMode1Threshold attribute is -62 dBm
|
||||
rather than the value of -99 dBm used for YansWifiPhy. This is because,
|
||||
unlike YansWifiPhy, where there are no foreign signals, CCA BUSY state
|
||||
will be raised for foreign signals that are higher than this 'energy
|
||||
detection' threshold (see section 16.4.8.5 in the 802.11-2012 standard
|
||||
for definition of CCA Mode 1).
|
||||
|
||||
To support the Spectrum channel, the ``YansWifiPhy`` transmit and receive methods
|
||||
were adapted to use the Spectrum channel API. This required developing
|
||||
a few ``SpectrumModel``-related classes. The class
|
||||
``WifiSpectrumValueHelper`` is used to create Wi-Fi signals with the
|
||||
spectrum framework and spread their energy across the bands. The
|
||||
spectrum is sub-divided into 312.5 KHz sub-bands (the width of an OFDM
|
||||
subcarrier). The power allocated to a particular channel
|
||||
is spread across the sub-bands roughly according to how power would
|
||||
be allocated to sub-carriers using an even distribution of power and
|
||||
assuming perfect transmit filters. This could be extended in the
|
||||
future to place power outside of the
|
||||
channel according to the real spectral mask. This should be
|
||||
done for future adjacent channel models but is not presently implemented.
|
||||
Similarly, on the receive side, a receiver filter mask can be defined;
|
||||
for this initial implementation, we implemented a perfect brick wall
|
||||
filter that is centered on the channel center frequency.
|
||||
|
||||
To support an easier user configuration experience, the existing
|
||||
YansWifi helper classes (in ``src/wifi/helper``) were copied and
|
||||
adapted to provide equivalent SpectrumWifi helper classes.
|
||||
|
||||
Finally, for reasons related to avoiding C++ multiple inheritance
|
||||
issues, a small forwarding class called ``WifiSpectrumPhyInterface``
|
||||
was inserted as a shim between the ``SpectrumWifiPhy`` and the
|
||||
Spectrum channel.
|
||||
|
||||
The MAC model
|
||||
=============
|
||||
|
||||
|
||||
@@ -52,7 +52,166 @@ in Figure :ref:`fig-nist-frame-success-rate`.
|
||||
|
||||
Frame error rate (NIST model) for OFDM Wi-Fi
|
||||
|
||||
|
||||
MAC validation
|
||||
**************
|
||||
Validation of the MAC layer has been performed in [baldo2010]_.
|
||||
|
||||
SpectrumWiFiPhy
|
||||
***************
|
||||
|
||||
The SpectrumWifiPhy implementation has been verified to produce equivalent
|
||||
results to the legacy YansWifiPhy by using the saturation and packet
|
||||
error rate programs (described below) and toggling the implementation
|
||||
between the two physical layers.
|
||||
|
||||
A basic unit test is provided using injection of hand-crafted packets to
|
||||
a receiving Phy object, controlling the timing and receive power of
|
||||
each packet arrival and checking the reception results. However, most of
|
||||
the testing of this Phy implementation has been performed using example
|
||||
programs described below, and during the course of a (separate) LTE/Wi-Fi
|
||||
coexistence study not documented herein.
|
||||
|
||||
Saturation performance
|
||||
======================
|
||||
|
||||
The program ``examples/wireless/wifi-spectrum-saturation-example.cc``
|
||||
allows user to select either the `SpectrumWifiPhy` or `YansWifiPhy` for
|
||||
saturation tests. The wifiType can be toggled by the argument
|
||||
``'--wifiType=ns3::YansWifiPhy'`` or ``--wifiType=ns3::SpectrumWifiPhy'``
|
||||
|
||||
There isn't any difference in the output, which is to be expected because
|
||||
this test is more of a test of the DCF than the physical layer.
|
||||
|
||||
By default, the program will use the `SpectrumWifiPhy` and will run
|
||||
for 10 seconds of saturating UDP data, with 802.11n features enabled.
|
||||
It produces this output for the main 802.11n rates (with short and long guard
|
||||
intervals):
|
||||
|
||||
::
|
||||
|
||||
wifiType: ns3::SpectrumWifiPhy distance: 1m
|
||||
index MCS width Rate (Mb/s) Tput (Mb/s) Received
|
||||
0 0 20 6.5 5.96219 5063
|
||||
1 1 20 13 11.9491 10147
|
||||
2 2 20 19.5 17.9172 15215
|
||||
3 3 20 26 23.9241 20316
|
||||
4 4 20 39 35.9427 30522
|
||||
5 5 20 52 47.9283 40700
|
||||
6 6 20 58.5 53.7445 45639
|
||||
7 7 20 65 59.4629 50495
|
||||
...
|
||||
63 15 40 300 240.884 204555
|
||||
|
||||
|
||||
The above output shows the first 8 (of 32) modes, and last mode, that will be
|
||||
output from the program. The first 8 modes correspond
|
||||
to short guard interval disabled and channel bonding disabled. The
|
||||
subsequent 24 modes run by this program are variations with short guard
|
||||
interval enabled (cases 9-16), and then with channel bonding enabled and
|
||||
short guard first disabled then enabled (cases 17-32). Cases 33-64 repeat
|
||||
the same configurations but for two spatial streams (MIMO abstraction).
|
||||
|
||||
When run with the legacy YansWifiPhy, as in ``./waf --run "wifi-spectrum-saturation-example --wifiType=ns3::YansWifiPhy"``, the same output is observed:
|
||||
|
||||
::
|
||||
|
||||
wifiType: ns3::YansWifiPhy distance: 1m
|
||||
index MCS width Rate (Mb/s) Tput (Mb/s) Received
|
||||
0 0 20 6.5 5.96219 5063
|
||||
1 1 20 13 11.9491 10147
|
||||
2 2 20 19.5 17.9172 15215
|
||||
3 3 20 26 23.9241 20316
|
||||
4 4 20 39 35.9427 30522
|
||||
5 5 20 52 47.9283 40700
|
||||
6 6 20 58.5 53.7445 45639
|
||||
|
||||
This is to be expected since YansWifiPhy and SpectrumWifiPhy use the
|
||||
same error rate model in this case.
|
||||
|
||||
Packet error rate performance
|
||||
=============================
|
||||
|
||||
The program ``examples/wireless/wifi-spectrum-per-example.cc`` allows users
|
||||
to select either `SpectrumWifiPhy` or `YansWifiPhy`, as above, and select
|
||||
the distance between the nodes, and to log the reception statistics and
|
||||
received SNR (as observed by the MonitorRx trace source), using a
|
||||
Friis propagation loss model. The transmit power is lowered from the default
|
||||
of 40 mW (16 dBm) to 1 dBm to lower the baseline SNR; the distance between
|
||||
the nodes can be changed to further change the SNR. By default, it steps
|
||||
through the same index values as in the saturation example (0 through 31)
|
||||
for a 50m distance, producing output such as:
|
||||
|
||||
::
|
||||
|
||||
wifiType: ns3::SpectrumWifiPhy distance: 50m; sent: 1000 TxPower: 1 dBm (1.3 mW)
|
||||
index MCS Rate (Mb/s) Tput (Mb/s) Received Signal (dBm) Noise (dBm) SNR (dB)
|
||||
0 0 6.5 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
1 1 13 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
2 2 19.5 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
3 3 26 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
4 4 39 0.7776 1000 -77.6633 -100.966 23.3027
|
||||
5 5 52 0 0 N/A N/A N/A
|
||||
6 6 58.5 0 0 N/A N/A N/A
|
||||
7 7 65 0 0 N/A N/A N/A
|
||||
|
||||
As in the above saturation example, running this program with YansWifiPhy
|
||||
will yield identical output.
|
||||
|
||||
Interference performance
|
||||
========================
|
||||
|
||||
The program ``examples/wireless/wifi-spectrum-per-interference.cc`` is based
|
||||
on the previous packet error rate example, but copies over the
|
||||
WaveformGenerator from the unlicensed LTE interferer test, to allow
|
||||
users to inject a non-Wi-Fi signal (using the ``--waveformPower`` argument)
|
||||
from the command line. Another difference with respect to the packet
|
||||
error rate example program is that the transmit power is set back to the
|
||||
default of 40 mW (16 dBm). By default, the interference generator is off,
|
||||
and the program should behave similarly to the other packet error rate example,
|
||||
but by adding small
|
||||
amounts of power (e.g. ``--waveformPower=0.001``), one will start to observe
|
||||
SNR degradation and frame loss.
|
||||
|
||||
Some sample output with default arguments (no interference) is:
|
||||
|
||||
::
|
||||
|
||||
./waf --run "wifi-spectrum-per-interference"
|
||||
|
||||
wifiType: ns3::SpectrumWifiPhy distance: 50m; sent: 1000 TxPower: 16 dBm (40 mW)
|
||||
index MCS Rate (Mb/s) Tput (Mb/s) Received Signal (dBm)Noi+Inf(dBm) SNR (dB)
|
||||
0 0 6.5 0.7776 1000 -62.6427 -100.966 38.3233
|
||||
1 1 13 0.7776 1000 -62.6427 -100.966 38.3233
|
||||
2 2 19.5 0.7776 1000 -62.6427 -100.966 38.3233
|
||||
3 3 26 0.7776 1000 -62.6427 -100.966 38.3233
|
||||
4 4 39 0.7776 1000 -62.6427 -100.966 38.3233
|
||||
5 5 52 0.7776 1000 -62.6427 -100.966 38.3233
|
||||
6 6 58.5 0.7776 1000 -62.6427 -100.966 38.3233
|
||||
...
|
||||
|
||||
while a small amount of waveform power will cause frame losses to occur at
|
||||
higher order modulations, due to lower SNR:
|
||||
|
||||
::
|
||||
|
||||
./waf --run "wifi-spectrum-per-interference --waveformPower=0.001"
|
||||
|
||||
wifiType: ns3::SpectrumWifiPhy distance: 50m; sent: 1000 TxPower: 16 dBm (40 mW)
|
||||
index MCS Rate (Mb/s) Tput (Mb/s) Received Signal (dBm)Noi+Inf(dBm) SNR (dB)
|
||||
0 0 6.5 0.7776 1000 -62.6427 -86.1031 23.4604
|
||||
1 1 13 0.7776 1000 -62.6427 -86.1031 23.4604
|
||||
2 2 19.5 0.7776 1000 -62.6427 -86.1032 23.4605
|
||||
3 3 26 0.7776 1000 -62.6427 -86.1031 23.4604
|
||||
4 4 39 0.7776 1000 -62.6427 -86.1032 23.4605
|
||||
5 5 52 0 0 N/A N/A N/A
|
||||
6 6 58.5 0 0 N/A N/A N/A
|
||||
...
|
||||
|
||||
If ns3::YansWifiPhy is selected as the wifiType, the waveform generator will
|
||||
not be enabled because only transmitters of type YansWifiPhy may be connected
|
||||
to a YansWifiChannel.
|
||||
|
||||
The interference signal as received by the sending node is typically below
|
||||
the default -62 dBm CCA Mode 1 threshold in this example. If it raises
|
||||
above, the sending node will suppress all transmissions.
|
||||
|
||||
|
||||
@@ -31,8 +31,10 @@ Attributes section. The scripts in ``examples/wireless`` can be browsed to
|
||||
see how this is done. Next, we describe the common steps to create a WifiNetDevice
|
||||
from the bottom layer (WifiChannel) up to the device layer (WifiNetDevice).
|
||||
|
||||
To create a WifiNetDevice, users need to configure mainly five steps:
|
||||
To create a WifiNetDevice, users need to follow these steps:
|
||||
|
||||
* Decide on which physical layer framework, the ``SpectrumWifiPhy`` or
|
||||
``YansWifiPhy``, to use. This will affect which Channel and Phy type to use.
|
||||
* Configure the WifiChannel: WifiChannel takes care of getting signal
|
||||
from one device to other devices on the same wifi channel.
|
||||
The main configurations of WifiChannel are propagation loss model and propagation delay model.
|
||||
@@ -488,6 +490,13 @@ for the standard. Setting ChannelWidth has no effect on Frequency or
|
||||
ChannelNumber. Setting Frequency will set ChannelNumber to either the
|
||||
defined value for that Wi-Fi standard, or to the value 0 if undefined.
|
||||
|
||||
SpectrumWifiPhyHelper
|
||||
=====================
|
||||
|
||||
The API for this helper closely tracks the API of the YansWifiPhyHelper,
|
||||
with the exception that a channel of type ``ns3::SpectrumChannel`` instead
|
||||
of type ``ns3::WifiChannel`` must be used with it.
|
||||
|
||||
WifiMacHelper
|
||||
=============
|
||||
|
||||
|
||||
687
src/wifi/helper/spectrum-wifi-helper.cc
Normal file
687
src/wifi/helper/spectrum-wifi-helper.cc
Normal file
@@ -0,0 +1,687 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2008 INRIA
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
* Sébastien Deronne <sebastien.deronne@gmail.com>
|
||||
*/
|
||||
|
||||
#include "ns3/trace-helper.h"
|
||||
#include "spectrum-wifi-helper.h"
|
||||
#include "ns3/error-rate-model.h"
|
||||
#include "ns3/propagation-loss-model.h"
|
||||
#include "ns3/propagation-delay-model.h"
|
||||
#include "ns3/spectrum-channel.h"
|
||||
#include "ns3/spectrum-wifi-phy.h"
|
||||
#include "ns3/ampdu-subframe-header.h"
|
||||
#include "ns3/wifi-net-device.h"
|
||||
#include "ns3/radiotap-header.h"
|
||||
#include "ns3/pcap-file-wrapper.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SpectrumWifiHelper");
|
||||
|
||||
static void
|
||||
AsciiPhyTransmitSinkWithContext (
|
||||
Ptr<OutputStreamWrapper> stream,
|
||||
std::string context,
|
||||
Ptr<const Packet> p,
|
||||
WifiMode mode,
|
||||
WifiPreamble preamble,
|
||||
uint8_t txLevel)
|
||||
{
|
||||
NS_LOG_FUNCTION (stream << context << p << mode << preamble << txLevel);
|
||||
*stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
AsciiPhyTransmitSinkWithoutContext (
|
||||
Ptr<OutputStreamWrapper> stream,
|
||||
Ptr<const Packet> p,
|
||||
WifiMode mode,
|
||||
WifiPreamble preamble,
|
||||
uint8_t txLevel)
|
||||
{
|
||||
NS_LOG_FUNCTION (stream << p << mode << preamble << txLevel);
|
||||
*stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
AsciiPhyReceiveSinkWithContext (
|
||||
Ptr<OutputStreamWrapper> stream,
|
||||
std::string context,
|
||||
Ptr<const Packet> p,
|
||||
double snr,
|
||||
WifiMode mode,
|
||||
enum WifiPreamble preamble)
|
||||
{
|
||||
NS_LOG_FUNCTION (stream << context << p << snr << mode << preamble);
|
||||
*stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
AsciiPhyReceiveSinkWithoutContext (
|
||||
Ptr<OutputStreamWrapper> stream,
|
||||
Ptr<const Packet> p,
|
||||
double snr,
|
||||
WifiMode mode,
|
||||
enum WifiPreamble preamble)
|
||||
{
|
||||
NS_LOG_FUNCTION (stream << p << snr << mode << preamble);
|
||||
*stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
|
||||
}
|
||||
|
||||
SpectrumWifiPhyHelper::SpectrumWifiPhyHelper ()
|
||||
: m_channel (0),
|
||||
m_pcapDlt (PcapHelper::DLT_IEEE802_11)
|
||||
{
|
||||
m_phy.SetTypeId ("ns3::SpectrumWifiPhy");
|
||||
}
|
||||
|
||||
SpectrumWifiPhyHelper
|
||||
SpectrumWifiPhyHelper::Default (void)
|
||||
{
|
||||
SpectrumWifiPhyHelper helper;
|
||||
helper.SetErrorRateModel ("ns3::NistErrorRateModel");
|
||||
return helper;
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyHelper::SetChannel (Ptr<SpectrumChannel> channel)
|
||||
{
|
||||
m_channel = channel;
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyHelper::SetChannel (std::string channelName)
|
||||
{
|
||||
Ptr<SpectrumChannel> channel = Names::Find<SpectrumChannel> (channelName);
|
||||
m_channel = channel;
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyHelper::Set (std::string name, const AttributeValue &v)
|
||||
{
|
||||
m_phy.Set (name, v);
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyHelper::SetErrorRateModel (std::string name,
|
||||
std::string n0, const AttributeValue &v0,
|
||||
std::string n1, const AttributeValue &v1,
|
||||
std::string n2, const AttributeValue &v2,
|
||||
std::string n3, const AttributeValue &v3,
|
||||
std::string n4, const AttributeValue &v4,
|
||||
std::string n5, const AttributeValue &v5,
|
||||
std::string n6, const AttributeValue &v6,
|
||||
std::string n7, const AttributeValue &v7)
|
||||
{
|
||||
m_errorRateModel = ObjectFactory ();
|
||||
m_errorRateModel.SetTypeId (name);
|
||||
m_errorRateModel.Set (n0, v0);
|
||||
m_errorRateModel.Set (n1, v1);
|
||||
m_errorRateModel.Set (n2, v2);
|
||||
m_errorRateModel.Set (n3, v3);
|
||||
m_errorRateModel.Set (n4, v4);
|
||||
m_errorRateModel.Set (n5, v5);
|
||||
m_errorRateModel.Set (n6, v6);
|
||||
m_errorRateModel.Set (n7, v7);
|
||||
}
|
||||
|
||||
Ptr<WifiPhy>
|
||||
SpectrumWifiPhyHelper::Create (Ptr<Node> node, Ptr<NetDevice> device) const
|
||||
{
|
||||
Ptr<SpectrumWifiPhy> phy = m_phy.Create<SpectrumWifiPhy> ();
|
||||
phy->CreateWifiSpectrumPhyInterface (device);
|
||||
Ptr<ErrorRateModel> error = m_errorRateModel.Create<ErrorRateModel> ();
|
||||
phy->SetErrorRateModel (error);
|
||||
phy->SetChannel (m_channel);
|
||||
phy->SetDevice (device);
|
||||
phy->SetMobility (node->GetObject<MobilityModel> ());
|
||||
return phy;
|
||||
}
|
||||
|
||||
static void
|
||||
PcapSniffTxEvent (
|
||||
Ptr<PcapFileWrapper> file,
|
||||
Ptr<const Packet> packet,
|
||||
uint16_t channelFreqMhz,
|
||||
uint16_t channelNumber,
|
||||
uint32_t rate,
|
||||
WifiPreamble preamble,
|
||||
WifiTxVector txVector,
|
||||
struct mpduInfo aMpdu)
|
||||
{
|
||||
uint32_t dlt = file->GetDataLinkType ();
|
||||
|
||||
switch (dlt)
|
||||
{
|
||||
case PcapHelper::DLT_IEEE802_11:
|
||||
file->Write (Simulator::Now (), packet);
|
||||
return;
|
||||
case PcapHelper::DLT_PRISM_HEADER:
|
||||
{
|
||||
NS_FATAL_ERROR ("PcapSniffTxEvent(): DLT_PRISM_HEADER not implemented");
|
||||
return;
|
||||
}
|
||||
case PcapHelper::DLT_IEEE802_11_RADIO:
|
||||
{
|
||||
Ptr<Packet> p = packet->Copy ();
|
||||
RadiotapHeader header;
|
||||
uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
|
||||
header.SetTsft (Simulator::Now ().GetMicroSeconds ());
|
||||
|
||||
//Our capture includes the FCS, so we set the flag to say so.
|
||||
frameFlags |= RadiotapHeader::FRAME_FLAG_FCS_INCLUDED;
|
||||
|
||||
if (preamble == WIFI_PREAMBLE_SHORT)
|
||||
{
|
||||
frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE;
|
||||
}
|
||||
|
||||
if (txVector.IsShortGuardInterval ())
|
||||
{
|
||||
frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_GUARD;
|
||||
}
|
||||
|
||||
header.SetFrameFlags (frameFlags);
|
||||
header.SetRate (rate);
|
||||
|
||||
uint16_t channelFlags = 0;
|
||||
switch (rate)
|
||||
{
|
||||
case 2: //1Mbps
|
||||
case 4: //2Mbps
|
||||
case 10: //5Mbps
|
||||
case 22: //11Mbps
|
||||
channelFlags |= RadiotapHeader::CHANNEL_FLAG_CCK;
|
||||
break;
|
||||
|
||||
default:
|
||||
channelFlags |= RadiotapHeader::CHANNEL_FLAG_OFDM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (channelFreqMhz < 2500)
|
||||
{
|
||||
channelFlags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
channelFlags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ;
|
||||
}
|
||||
|
||||
header.SetChannelFrequencyAndFlags (channelFreqMhz, channelFlags);
|
||||
|
||||
if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF || preamble == WIFI_PREAMBLE_NONE)
|
||||
{
|
||||
uint8_t mcsRate = 0;
|
||||
uint8_t mcsKnown = RadiotapHeader::MCS_KNOWN_NONE;
|
||||
uint8_t mcsFlags = RadiotapHeader::MCS_FLAGS_NONE;
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_INDEX;
|
||||
mcsRate = rate - 128;
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_BANDWIDTH;
|
||||
if (txVector.GetChannelWidth () == 40)
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_BANDWIDTH_40;
|
||||
}
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_GUARD_INTERVAL;
|
||||
if (txVector.IsShortGuardInterval ())
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_GUARD_INTERVAL;
|
||||
}
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_HT_FORMAT;
|
||||
if (preamble == WIFI_PREAMBLE_HT_GF)
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_HT_GREENFIELD;
|
||||
}
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS;
|
||||
if (txVector.GetNess () & 0x01) //bit 1
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
|
||||
}
|
||||
if (txVector.GetNess () & 0x02) //bit 2
|
||||
{
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
|
||||
}
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_FEC_TYPE; //only BCC is currently supported
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_STBC;
|
||||
if (txVector.IsStbc ())
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_STBC_STREAMS;
|
||||
}
|
||||
|
||||
header.SetMcsFields (mcsKnown, mcsFlags, mcsRate);
|
||||
}
|
||||
|
||||
if (txVector.IsAggregation ())
|
||||
{
|
||||
uint16_t ampduStatusFlags = RadiotapHeader::A_MPDU_STATUS_NONE;
|
||||
ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
|
||||
/* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
|
||||
AmpduSubframeHeader hdr;
|
||||
uint32_t extractedLength;
|
||||
p->RemoveHeader (hdr);
|
||||
extractedLength = hdr.GetLength ();
|
||||
p = p->CreateFragment (0, static_cast<uint32_t> (extractedLength));
|
||||
if (aMpdu.type == LAST_MPDU_IN_AGGREGATE || (hdr.GetEof () == true && hdr.GetLength () > 0))
|
||||
{
|
||||
ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST;
|
||||
}
|
||||
header.SetAmpduStatus (aMpdu.mpduRefNumber, ampduStatusFlags, hdr.GetCrc ());
|
||||
}
|
||||
|
||||
if (preamble == WIFI_PREAMBLE_VHT)
|
||||
{
|
||||
uint16_t vhtKnown = RadiotapHeader::VHT_KNOWN_NONE;
|
||||
uint8_t vhtFlags = RadiotapHeader::VHT_FLAGS_NONE;
|
||||
uint8_t vhtBandwidth = 0;
|
||||
uint8_t vhtMcsNss[4] = {0,0,0,0};
|
||||
uint8_t vhtCoding = 0;
|
||||
uint8_t vhtGroupId = 0;
|
||||
uint16_t vhtPartialAid = 0;
|
||||
|
||||
vhtKnown |= RadiotapHeader::VHT_KNOWN_STBC;
|
||||
if (txVector.IsStbc ())
|
||||
{
|
||||
vhtFlags |= RadiotapHeader::VHT_FLAGS_STBC;
|
||||
}
|
||||
|
||||
vhtKnown |= RadiotapHeader::VHT_KNOWN_GUARD_INTERVAL;
|
||||
if (txVector.IsShortGuardInterval ())
|
||||
{
|
||||
vhtFlags |= RadiotapHeader::VHT_FLAGS_GUARD_INTERVAL;
|
||||
}
|
||||
|
||||
vhtKnown |= RadiotapHeader::VHT_KNOWN_BEAMFORMED; //Beamforming is currently not supported
|
||||
|
||||
vhtKnown |= RadiotapHeader::VHT_KNOWN_BANDWIDTH;
|
||||
//not all bandwidth values are currently supported
|
||||
if (txVector.GetChannelWidth () == 40)
|
||||
{
|
||||
vhtBandwidth = 1;
|
||||
}
|
||||
else if (txVector.GetChannelWidth () == 80)
|
||||
{
|
||||
vhtBandwidth = 4;
|
||||
}
|
||||
else if (txVector.GetChannelWidth () == 160)
|
||||
{
|
||||
vhtBandwidth = 11;
|
||||
}
|
||||
|
||||
//only SU PPDUs are currently supported
|
||||
vhtMcsNss[0] |= (txVector.GetNss () & 0x0f);
|
||||
vhtMcsNss[0] |= (((rate - 128) << 4) & 0xf0);
|
||||
|
||||
header.SetVhtFields (vhtKnown, vhtFlags, vhtBandwidth, vhtMcsNss, vhtCoding, vhtGroupId, vhtPartialAid);
|
||||
}
|
||||
|
||||
p->AddHeader (header);
|
||||
file->Write (Simulator::Now (), p);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
NS_ABORT_MSG ("PcapSniffTxEvent(): Unexpected data link type " << dlt);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PcapSniffRxEvent (
|
||||
Ptr<PcapFileWrapper> file,
|
||||
Ptr<const Packet> packet,
|
||||
uint16_t channelFreqMhz,
|
||||
uint16_t channelNumber,
|
||||
uint32_t rate,
|
||||
WifiPreamble preamble,
|
||||
WifiTxVector txVector,
|
||||
struct mpduInfo aMpdu,
|
||||
struct signalNoiseDbm signalNoise)
|
||||
{
|
||||
uint32_t dlt = file->GetDataLinkType ();
|
||||
|
||||
switch (dlt)
|
||||
{
|
||||
case PcapHelper::DLT_IEEE802_11:
|
||||
file->Write (Simulator::Now (), packet);
|
||||
return;
|
||||
case PcapHelper::DLT_PRISM_HEADER:
|
||||
{
|
||||
NS_FATAL_ERROR ("PcapSniffRxEvent(): DLT_PRISM_HEADER not implemented");
|
||||
return;
|
||||
}
|
||||
case PcapHelper::DLT_IEEE802_11_RADIO:
|
||||
{
|
||||
Ptr<Packet> p = packet->Copy ();
|
||||
RadiotapHeader header;
|
||||
uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
|
||||
header.SetTsft (Simulator::Now ().GetMicroSeconds ());
|
||||
|
||||
//Our capture includes the FCS, so we set the flag to say so.
|
||||
frameFlags |= RadiotapHeader::FRAME_FLAG_FCS_INCLUDED;
|
||||
|
||||
if (preamble == WIFI_PREAMBLE_SHORT)
|
||||
{
|
||||
frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE;
|
||||
}
|
||||
|
||||
if (txVector.IsShortGuardInterval ())
|
||||
{
|
||||
frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_GUARD;
|
||||
}
|
||||
|
||||
header.SetFrameFlags (frameFlags);
|
||||
header.SetRate (rate);
|
||||
|
||||
uint16_t channelFlags = 0;
|
||||
switch (rate)
|
||||
{
|
||||
case 2: //1Mbps
|
||||
case 4: //2Mbps
|
||||
case 10: //5Mbps
|
||||
case 22: //11Mbps
|
||||
channelFlags |= RadiotapHeader::CHANNEL_FLAG_CCK;
|
||||
break;
|
||||
|
||||
default:
|
||||
channelFlags |= RadiotapHeader::CHANNEL_FLAG_OFDM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (channelFreqMhz < 2500)
|
||||
{
|
||||
channelFlags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
channelFlags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ;
|
||||
}
|
||||
|
||||
header.SetChannelFrequencyAndFlags (channelFreqMhz, channelFlags);
|
||||
|
||||
header.SetAntennaSignalPower (signalNoise.signal);
|
||||
header.SetAntennaNoisePower (signalNoise.noise);
|
||||
|
||||
if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF || preamble == WIFI_PREAMBLE_NONE)
|
||||
{
|
||||
uint8_t mcsRate = 0;
|
||||
uint8_t mcsKnown = RadiotapHeader::MCS_KNOWN_NONE;
|
||||
uint8_t mcsFlags = RadiotapHeader::MCS_FLAGS_NONE;
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_INDEX;
|
||||
mcsRate = rate - 128;
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_BANDWIDTH;
|
||||
if (txVector.GetChannelWidth () == 40)
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_BANDWIDTH_40;
|
||||
}
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_GUARD_INTERVAL;
|
||||
if (txVector.IsShortGuardInterval ())
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_GUARD_INTERVAL;
|
||||
}
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_HT_FORMAT;
|
||||
if (preamble == WIFI_PREAMBLE_HT_GF)
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_HT_GREENFIELD;
|
||||
}
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS;
|
||||
if (txVector.GetNess () & 0x01) //bit 1
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
|
||||
}
|
||||
if (txVector.GetNess () & 0x02) //bit 2
|
||||
{
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
|
||||
}
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_FEC_TYPE; //only BCC is currently supported
|
||||
|
||||
mcsKnown |= RadiotapHeader::MCS_KNOWN_STBC;
|
||||
if (txVector.IsStbc ())
|
||||
{
|
||||
mcsFlags |= RadiotapHeader::MCS_FLAGS_STBC_STREAMS;
|
||||
}
|
||||
|
||||
header.SetMcsFields (mcsKnown, mcsFlags, mcsRate);
|
||||
}
|
||||
|
||||
if (txVector.IsAggregation ())
|
||||
{
|
||||
uint16_t ampduStatusFlags = RadiotapHeader::A_MPDU_STATUS_NONE;
|
||||
ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_DELIMITER_CRC_KNOWN;
|
||||
ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
|
||||
/* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
|
||||
AmpduSubframeHeader hdr;
|
||||
uint32_t extractedLength;
|
||||
p->RemoveHeader (hdr);
|
||||
extractedLength = hdr.GetLength ();
|
||||
p = p->CreateFragment (0, static_cast<uint32_t> (extractedLength));
|
||||
if (aMpdu.type == LAST_MPDU_IN_AGGREGATE || (hdr.GetEof () == true && hdr.GetLength () > 0))
|
||||
{
|
||||
ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST;
|
||||
}
|
||||
header.SetAmpduStatus (aMpdu.mpduRefNumber, ampduStatusFlags, hdr.GetCrc ());
|
||||
}
|
||||
|
||||
if (preamble == WIFI_PREAMBLE_VHT)
|
||||
{
|
||||
uint16_t vhtKnown = RadiotapHeader::VHT_KNOWN_NONE;
|
||||
uint8_t vhtFlags = RadiotapHeader::VHT_FLAGS_NONE;
|
||||
uint8_t vhtBandwidth = 0;
|
||||
uint8_t vhtMcsNss[4] = {0,0,0,0};
|
||||
uint8_t vhtCoding = 0;
|
||||
uint8_t vhtGroupId = 0;
|
||||
uint16_t vhtPartialAid = 0;
|
||||
|
||||
vhtKnown |= RadiotapHeader::VHT_KNOWN_STBC;
|
||||
if (txVector.IsStbc ())
|
||||
{
|
||||
vhtFlags |= RadiotapHeader::VHT_FLAGS_STBC;
|
||||
}
|
||||
|
||||
vhtKnown |= RadiotapHeader::VHT_KNOWN_GUARD_INTERVAL;
|
||||
if (txVector.IsShortGuardInterval ())
|
||||
{
|
||||
vhtFlags |= RadiotapHeader::VHT_FLAGS_GUARD_INTERVAL;
|
||||
}
|
||||
|
||||
vhtKnown |= RadiotapHeader::VHT_KNOWN_BEAMFORMED; //Beamforming is currently not supported
|
||||
|
||||
vhtKnown |= RadiotapHeader::VHT_KNOWN_BANDWIDTH;
|
||||
//not all bandwidth values are currently supported
|
||||
if (txVector.GetChannelWidth () == 40)
|
||||
{
|
||||
vhtBandwidth = 1;
|
||||
}
|
||||
else if (txVector.GetChannelWidth () == 80)
|
||||
{
|
||||
vhtBandwidth = 4;
|
||||
}
|
||||
else if (txVector.GetChannelWidth () == 160)
|
||||
{
|
||||
vhtBandwidth = 11;
|
||||
}
|
||||
|
||||
//only SU PPDUs are currently supported
|
||||
vhtMcsNss[0] |= (txVector.GetNss () & 0x0f);
|
||||
vhtMcsNss[0] |= (((rate - 128) << 4) & 0xf0);
|
||||
|
||||
header.SetVhtFields (vhtKnown, vhtFlags, vhtBandwidth, vhtMcsNss, vhtCoding, vhtGroupId, vhtPartialAid);
|
||||
}
|
||||
|
||||
p->AddHeader (header);
|
||||
file->Write (Simulator::Now (), p);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
NS_ABORT_MSG ("PcapSniffRxEvent(): Unexpected data link type " << dlt);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyHelper::SetPcapDataLinkType (enum SupportedPcapDataLinkTypes dlt)
|
||||
{
|
||||
switch (dlt)
|
||||
{
|
||||
case DLT_IEEE802_11:
|
||||
m_pcapDlt = PcapHelper::DLT_IEEE802_11;
|
||||
return;
|
||||
case DLT_PRISM_HEADER:
|
||||
m_pcapDlt = PcapHelper::DLT_PRISM_HEADER;
|
||||
return;
|
||||
case DLT_IEEE802_11_RADIO:
|
||||
m_pcapDlt = PcapHelper::DLT_IEEE802_11_RADIO;
|
||||
return;
|
||||
default:
|
||||
NS_ABORT_MSG ("SpectrumWifiPhyHelper::SetPcapFormat(): Unexpected format");
|
||||
}
|
||||
}
|
||||
|
||||
PcapHelper::DataLinkType
|
||||
SpectrumWifiPhyHelper::GetPcapDataLinkType (void) const
|
||||
{
|
||||
return m_pcapDlt;
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
|
||||
{
|
||||
//All of the Pcap enable functions vector through here including the ones
|
||||
//that are wandering through all of devices on perhaps all of the nodes in
|
||||
//the system. We can only deal with devices of type WifiNetDevice.
|
||||
Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice> ();
|
||||
if (device == 0)
|
||||
{
|
||||
NS_LOG_INFO ("SpectrumWifiHelper::EnablePcapInternal(): Device " << &device << " not of type ns3::WifiNetDevice");
|
||||
return;
|
||||
}
|
||||
|
||||
Ptr<WifiPhy> phy = device->GetPhy ();
|
||||
NS_ABORT_MSG_IF (phy == 0, "SpectrumWifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set");
|
||||
|
||||
PcapHelper pcapHelper;
|
||||
|
||||
std::string filename;
|
||||
if (explicitFilename)
|
||||
{
|
||||
filename = prefix;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = pcapHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, m_pcapDlt);
|
||||
|
||||
phy->TraceConnectWithoutContext ("MonitorSnifferTx", MakeBoundCallback (&PcapSniffTxEvent, file));
|
||||
phy->TraceConnectWithoutContext ("MonitorSnifferRx", MakeBoundCallback (&PcapSniffRxEvent, file));
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyHelper::EnableAsciiInternal (
|
||||
Ptr<OutputStreamWrapper> stream,
|
||||
std::string prefix,
|
||||
Ptr<NetDevice> nd,
|
||||
bool explicitFilename)
|
||||
{
|
||||
//All of the ascii enable functions vector through here including the ones
|
||||
//that are wandering through all of devices on perhaps all of the nodes in
|
||||
//the system. We can only deal with devices of type WifiNetDevice.
|
||||
Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice> ();
|
||||
if (device == 0)
|
||||
{
|
||||
NS_LOG_INFO ("SpectrumWifiHelper::EnableAsciiInternal(): Device " << device << " not of type ns3::WifiNetDevice");
|
||||
return;
|
||||
}
|
||||
|
||||
//Our trace sinks are going to use packet printing, so we have to make sure
|
||||
//that is turned on.
|
||||
Packet::EnablePrinting ();
|
||||
|
||||
uint32_t nodeid = nd->GetNode ()->GetId ();
|
||||
uint32_t deviceid = nd->GetIfIndex ();
|
||||
std::ostringstream oss;
|
||||
|
||||
//If we are not provided an OutputStreamWrapper, we are expected to create
|
||||
//one using the usual trace filename conventions and write our traces
|
||||
//without a context since there will be one file per context and therefore
|
||||
//the context would be redundant.
|
||||
if (stream == 0)
|
||||
{
|
||||
//Set up an output stream object to deal with private ofstream copy
|
||||
//constructor and lifetime issues. Let the helper decide the actual
|
||||
//name of the file given the prefix.
|
||||
AsciiTraceHelper asciiTraceHelper;
|
||||
|
||||
std::string filename;
|
||||
if (explicitFilename)
|
||||
{
|
||||
filename = prefix;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
|
||||
//We could go poking through the phy and the state looking for the
|
||||
//correct trace source, but we can let Config deal with that with
|
||||
//some search cost. Since this is presumably happening at topology
|
||||
//creation time, it doesn't seem much of a price to pay.
|
||||
oss.str ("");
|
||||
oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/RxOk";
|
||||
Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&AsciiPhyReceiveSinkWithoutContext, theStream));
|
||||
|
||||
oss.str ("");
|
||||
oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/Tx";
|
||||
Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&AsciiPhyTransmitSinkWithoutContext, theStream));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//If we are provided an OutputStreamWrapper, we are expected to use it, and
|
||||
//to provide a context. We are free to come up with our own context if we
|
||||
//want, and use the AsciiTraceHelper Hook*WithContext functions, but for
|
||||
//compatibility and simplicity, we just use Config::Connect and let it deal
|
||||
//with coming up with a context.
|
||||
oss.str ("");
|
||||
oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/RxOk";
|
||||
Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyReceiveSinkWithContext, stream));
|
||||
|
||||
oss.str ("");
|
||||
oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/Tx";
|
||||
Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyTransmitSinkWithContext, stream));
|
||||
}
|
||||
|
||||
} //namespace ns3
|
||||
187
src/wifi/helper/spectrum-wifi-helper.h
Normal file
187
src/wifi/helper/spectrum-wifi-helper.h
Normal file
@@ -0,0 +1,187 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2008 INRIA
|
||||
*
|
||||
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#ifndef SPECTRUM_WIFI_HELPER_H
|
||||
#define SPECTRUM_WIFI_HELPER_H
|
||||
|
||||
#include "wifi-helper.h"
|
||||
#include "ns3/trace-helper.h"
|
||||
#include "ns3/wifi-phy.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class SpectrumChannel;
|
||||
|
||||
/**
|
||||
* \brief Make it easy to create and manage PHY objects for the spectrum model.
|
||||
*
|
||||
* The Pcap and ascii traces generated by the EnableAscii and EnablePcap methods defined
|
||||
* in this class correspond to PHY-level traces and come to us via WifiPhyHelper
|
||||
*
|
||||
*/
|
||||
class SpectrumWifiPhyHelper : public WifiPhyHelper,
|
||||
public PcapHelperForDevice,
|
||||
public AsciiTraceHelperForDevice
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a phy helper without any parameter set. The user must set
|
||||
* them all to be able to call Install later.
|
||||
*/
|
||||
SpectrumWifiPhyHelper ();
|
||||
|
||||
/**
|
||||
* Create a phy helper in a default working state.
|
||||
*/
|
||||
static SpectrumWifiPhyHelper Default (void);
|
||||
|
||||
/**
|
||||
* \param channel the channel to associate to this helper
|
||||
*
|
||||
* Every PHY created by a call to Install is associated to this channel.
|
||||
*/
|
||||
void SetChannel (Ptr<SpectrumChannel> channel);
|
||||
/**
|
||||
* \param channelName The name of the channel to associate to this helper
|
||||
*
|
||||
* Every PHY created by a call to Install is associated to this channel.
|
||||
*/
|
||||
void SetChannel (std::string channelName);
|
||||
/**
|
||||
* \param name the name of the attribute to set
|
||||
* \param v the value of the attribute
|
||||
*
|
||||
* Set an attribute of the underlying PHY object.
|
||||
*/
|
||||
void Set (std::string name, const AttributeValue &v);
|
||||
/**
|
||||
* \param name the name of the error rate model to set.
|
||||
* \param n0 the name of the attribute to set
|
||||
* \param v0 the value of the attribute to set
|
||||
* \param n1 the name of the attribute to set
|
||||
* \param v1 the value of the attribute to set
|
||||
* \param n2 the name of the attribute to set
|
||||
* \param v2 the value of the attribute to set
|
||||
* \param n3 the name of the attribute to set
|
||||
* \param v3 the value of the attribute to set
|
||||
* \param n4 the name of the attribute to set
|
||||
* \param v4 the value of the attribute to set
|
||||
* \param n5 the name of the attribute to set
|
||||
* \param v5 the value of the attribute to set
|
||||
* \param n6 the name of the attribute to set
|
||||
* \param v6 the value of the attribute to set
|
||||
* \param n7 the name of the attribute to set
|
||||
* \param v7 the value of the attribute to set
|
||||
*
|
||||
* Set the error rate model and its attributes to use when Install is called.
|
||||
*/
|
||||
void SetErrorRateModel (std::string name,
|
||||
std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
|
||||
std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
|
||||
std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
|
||||
std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
|
||||
std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
|
||||
std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
|
||||
std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
|
||||
std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
|
||||
|
||||
/**
|
||||
* An enumeration of the pcap data link types (DLTs) which this helper
|
||||
* supports. See http://wiki.wireshark.org/Development/LibpcapFileFormat
|
||||
* for more information on these formats.
|
||||
*/
|
||||
enum SupportedPcapDataLinkTypes
|
||||
{
|
||||
DLT_IEEE802_11 = PcapHelper::DLT_IEEE802_11, /**< IEEE 802.11 Wireless LAN headers on packets */
|
||||
DLT_PRISM_HEADER = PcapHelper::DLT_PRISM_HEADER, /**< Include Prism monitor mode information */
|
||||
DLT_IEEE802_11_RADIO = PcapHelper::DLT_IEEE802_11_RADIO /**< Include Radiotap link layer information */
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the data link type of PCAP traces to be used. This function has to be
|
||||
* called before EnablePcap(), so that the header of the pcap file can be
|
||||
* written correctly.
|
||||
*
|
||||
* @see SupportedPcapDataLinkTypes
|
||||
*
|
||||
* @param dlt The data link type of the pcap file (and packets) to be used
|
||||
*/
|
||||
void SetPcapDataLinkType (enum SupportedPcapDataLinkTypes dlt);
|
||||
|
||||
/**
|
||||
* Get the data link type of PCAP traces to be used.
|
||||
*
|
||||
* @see SupportedPcapDataLinkTypes
|
||||
*
|
||||
* @returns The data link type of the pcap file (and packets) to be used
|
||||
*/
|
||||
PcapHelper::DataLinkType GetPcapDataLinkType (void) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* \param node the node on which we wish to create a wifi PHY
|
||||
* \param device the device within which this PHY will be created
|
||||
* \returns a newly-created PHY object.
|
||||
*
|
||||
* This method implements the pure virtual method defined in \ref ns3::WifiPhyHelper.
|
||||
*/
|
||||
virtual Ptr<WifiPhy> Create (Ptr<Node> node, Ptr<NetDevice> device) const;
|
||||
|
||||
/**
|
||||
* @brief Enable pcap output the indicated net device.
|
||||
*
|
||||
* NetDevice-specific implementation mechanism for hooking the trace and
|
||||
* writing to the trace file.
|
||||
*
|
||||
* @param prefix Filename prefix to use for pcap files.
|
||||
* @param nd Net device for which you want to enable tracing.
|
||||
* @param promiscuous If true capture all possible packets available at the device.
|
||||
* @param explicitFilename Treat the prefix as an explicit filename if true
|
||||
*/
|
||||
virtual void EnablePcapInternal (std::string prefix,
|
||||
Ptr<NetDevice> nd,
|
||||
bool promiscuous,
|
||||
bool explicitFilename);
|
||||
|
||||
/**
|
||||
* \brief Enable ascii trace output on the indicated net device.
|
||||
*
|
||||
* NetDevice-specific implementation mechanism for hooking the trace and
|
||||
* writing to the trace file.
|
||||
*
|
||||
* \param stream The output stream object to use when logging ascii traces.
|
||||
* \param prefix Filename prefix to use for ascii trace files.
|
||||
* \param nd Net device for which you want to enable tracing.
|
||||
* \param explicitFilename Treat the prefix as an explicit filename if true
|
||||
*/
|
||||
virtual void EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
|
||||
std::string prefix,
|
||||
Ptr<NetDevice> nd,
|
||||
bool explicitFilename);
|
||||
|
||||
ObjectFactory m_phy;
|
||||
ObjectFactory m_errorRateModel;
|
||||
Ptr<SpectrumChannel> m_channel;
|
||||
PcapHelper::DataLinkType m_pcapDlt;
|
||||
};
|
||||
|
||||
} //namespace ns3
|
||||
|
||||
#endif /* SPECTRUM_WIFI_HELPER_H */
|
||||
@@ -162,6 +162,14 @@ InterferenceHelper::Add (uint32_t size, WifiTxVector txVector,
|
||||
return event;
|
||||
}
|
||||
|
||||
void
|
||||
InterferenceHelper::AddForeignSignal (Time duration, double rxPowerW)
|
||||
{
|
||||
// Parameters other than duration and rxPowerW are unused for this type
|
||||
// of signal, so we provide dummy versions
|
||||
WifiTxVector fakeTxVector;
|
||||
Add (0, fakeTxVector, WIFI_PREAMBLE_NONE, duration, rxPowerW);
|
||||
}
|
||||
|
||||
void
|
||||
InterferenceHelper::SetNoiseFigure (double value)
|
||||
|
||||
@@ -183,6 +183,12 @@ private:
|
||||
enum WifiPreamble preamble,
|
||||
Time duration, double rxPower);
|
||||
|
||||
/**
|
||||
* Add a non-Wifi signal to interference helper.
|
||||
* \param duration the duration of the signal
|
||||
* \param rxPower receive power (W)
|
||||
*/
|
||||
void AddForeignSignal (Time duration, double rxPower);
|
||||
/**
|
||||
* Calculate the SNIR at the start of the plcp payload and accumulate
|
||||
* all SNIR changes in the snir vector.
|
||||
|
||||
1663
src/wifi/model/spectrum-wifi-phy.cc
Normal file
1663
src/wifi/model/spectrum-wifi-phy.cc
Normal file
File diff suppressed because it is too large
Load Diff
685
src/wifi/model/spectrum-wifi-phy.h
Normal file
685
src/wifi/model/spectrum-wifi-phy.h
Normal file
@@ -0,0 +1,685 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2005,2006 INRIA
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
* Ghada Badawy <gbadawy@gmail.com>
|
||||
* Sébastien Deronne <sebastien.deronne@gmail.com>
|
||||
*
|
||||
* Ported from yans-wifi-phy.h by several contributors starting
|
||||
* with Nicola Baldo and Dean Armstrong
|
||||
*/
|
||||
|
||||
#ifndef SPECTRUM_WIFI_PHY_H
|
||||
#define SPECTRUM_WIFI_PHY_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/traced-callback.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
#include "ns3/mobility-model.h"
|
||||
#include "wifi-phy.h"
|
||||
#include "wifi-mode.h"
|
||||
#include "wifi-preamble.h"
|
||||
#include "wifi-phy-standard.h"
|
||||
#include "interference-helper.h"
|
||||
|
||||
#include "wifi-spectrum-phy-interface.h"
|
||||
#include "ns3/spectrum-channel.h"
|
||||
#include "ns3/spectrum-interference.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
#define VHT_PHY 126
|
||||
#define HT_PHY 127
|
||||
|
||||
class WifiPhyStateHelper;
|
||||
class AntennaModel;
|
||||
|
||||
/**
|
||||
* \brief 802.11 PHY layer model
|
||||
* \ingroup wifi
|
||||
*
|
||||
* This PHY implements a spectrum-aware enhancement of the 802.11 SpectrumWifiPhy
|
||||
* model.
|
||||
*
|
||||
* This PHY model depends on a channel loss and delay
|
||||
* model as provided by the ns3::SpectrumPropagationLossModel
|
||||
* and ns3::PropagationDelayModel classes.
|
||||
*
|
||||
*/
|
||||
class SpectrumWifiPhy : public WifiPhy
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
SpectrumWifiPhy ();
|
||||
virtual ~SpectrumWifiPhy ();
|
||||
|
||||
/**
|
||||
* Set the SpectrumChannel this SpectrumWifiPhy is to be connected to.
|
||||
*
|
||||
* \param channel the SpectrumChannel this SpectrumWifiPhy is to be connected to
|
||||
*/
|
||||
void SetChannel (Ptr<SpectrumChannel> channel);
|
||||
/**
|
||||
* \return the required time for channel switch operation of this WifiPhy
|
||||
*/
|
||||
Time GetChannelSwitchDelay (void) const;
|
||||
/**
|
||||
* Add a channel number to the list of operational channels. This method
|
||||
* is used to support scanning for strongest base station.
|
||||
*
|
||||
* \param channelNumber the channel number to add
|
||||
*/
|
||||
void AddOperationalChannel (uint16_t channelNumber);
|
||||
/**
|
||||
* Return a list of channels to which it may be possible to roam
|
||||
* By default, this method will return the current channel number followed
|
||||
* by any other channel numbers that have been added.
|
||||
*
|
||||
* \return vector of channel numbers to which it may be possible to roam
|
||||
*/
|
||||
std::vector<uint16_t> GetOperationalChannelList (void) const;
|
||||
/**
|
||||
* Clear the list of operational channels.
|
||||
*/
|
||||
void ClearOperationalChannelList (void);
|
||||
|
||||
/**
|
||||
* 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 mpdutype the type of the MPDU as defined in WifiPhy::mpduType.
|
||||
* \param rxDuration the duration needed for the reception of the packet
|
||||
*/
|
||||
void StartReceivePreambleAndHeader (Ptr<Packet> packet,
|
||||
double rxPowerDbm,
|
||||
WifiTxVector txVector,
|
||||
WifiPreamble preamble,
|
||||
enum mpduType mpdutype,
|
||||
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 mpdutype the type of the MPDU as defined in WifiPhy::mpduType.
|
||||
* \param event the corresponding event of the first time the packet arrives
|
||||
*/
|
||||
void StartReceivePacket (Ptr<Packet> packet,
|
||||
WifiTxVector txVector,
|
||||
WifiPreamble preamble,
|
||||
enum mpduType mpdutype,
|
||||
Ptr<InterferenceHelper::Event> event);
|
||||
|
||||
/**
|
||||
* Sets the RX loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver.
|
||||
*
|
||||
* \param noiseFigureDb noise figure in dB
|
||||
*/
|
||||
void SetRxNoiseFigure (double noiseFigureDb);
|
||||
/**
|
||||
* Sets the minimum available transmission power level (dBm).
|
||||
*
|
||||
* \param start the minimum transmission power level (dBm)
|
||||
*/
|
||||
void SetTxPowerStart (double start);
|
||||
/**
|
||||
* Sets the maximum available transmission power level (dBm).
|
||||
*
|
||||
* \param end the maximum transmission power level (dBm)
|
||||
*/
|
||||
void SetTxPowerEnd (double end);
|
||||
/**
|
||||
* Sets the number of transmission power levels available between the
|
||||
* minimum level and the maximum level. Transmission power levels are
|
||||
* equally separated (in dBm) with the minimum and the maximum included.
|
||||
*
|
||||
* \param n the number of available levels
|
||||
*/
|
||||
void SetNTxPower (uint32_t n);
|
||||
/**
|
||||
* Sets the transmission gain (dB).
|
||||
*
|
||||
* \param gain the transmission gain in dB
|
||||
*/
|
||||
void SetTxGain (double gain);
|
||||
/**
|
||||
* Sets the reception gain (dB).
|
||||
*
|
||||
* \param gain the reception gain in dB
|
||||
*/
|
||||
void SetRxGain (double gain);
|
||||
/**
|
||||
* Sets the energy detection threshold (dBm).
|
||||
* The energy of a received signal should be higher than
|
||||
* this threshold (dbm) to allow the PHY layer to detect the signal.
|
||||
*
|
||||
* \param threshold the energy detction threshold in dBm
|
||||
*/
|
||||
void SetEdThreshold (double threshold);
|
||||
/**
|
||||
* Sets the CCA threshold (dBm). The energy of a received signal
|
||||
* should be higher than this threshold to allow the PHY
|
||||
* layer to declare CCA BUSY state.
|
||||
*
|
||||
* \param threshold the CCA threshold in dBm
|
||||
*/
|
||||
void SetCcaMode1Threshold (double threshold);
|
||||
/**
|
||||
* Sets the error rate model.
|
||||
*
|
||||
* \param rate the error rate model
|
||||
*/
|
||||
void SetErrorRateModel (Ptr<ErrorRateModel> rate);
|
||||
/**
|
||||
* Sets the device this PHY is associated with.
|
||||
*
|
||||
* \param device the device this PHY is associated with
|
||||
*/
|
||||
void SetDevice (Ptr<NetDevice> device);
|
||||
/**
|
||||
* \brief assign a mobility model to this device
|
||||
*
|
||||
* This method allows a user to specify a mobility model that should be
|
||||
* associated with this physical layer. Calling this method is optional
|
||||
* and only necessary if the user wants to override the mobility model
|
||||
* that is aggregated to the node.
|
||||
*
|
||||
* \param mobility the mobility model this PHY is associated with
|
||||
*/
|
||||
void SetMobility (Ptr<MobilityModel> mobility);
|
||||
/**
|
||||
* Return the RX noise figure (dBm).
|
||||
*
|
||||
* \return the RX noise figure in dBm
|
||||
*/
|
||||
double GetRxNoiseFigure (void) const;
|
||||
/**
|
||||
* Return the transmission gain (dB).
|
||||
*
|
||||
* \return the transmission gain in dB
|
||||
*/
|
||||
double GetTxGain (void) const;
|
||||
/**
|
||||
* Return the reception gain (dB).
|
||||
*
|
||||
* \return the reception gain in dB
|
||||
*/
|
||||
double GetRxGain (void) const;
|
||||
/**
|
||||
* Return the energy detection threshold (dBm).
|
||||
*
|
||||
* \return the energy detection threshold in dBm
|
||||
*/
|
||||
double GetEdThreshold (void) const;
|
||||
/**
|
||||
* Return the CCA threshold (dBm).
|
||||
*
|
||||
* \return the CCA threshold in dBm
|
||||
*/
|
||||
double GetCcaMode1Threshold (void) const;
|
||||
/**
|
||||
* Return the error rate model this PHY is using.
|
||||
*
|
||||
* \return the error rate model this PHY is using
|
||||
*/
|
||||
Ptr<ErrorRateModel> GetErrorRateModel (void) const;
|
||||
/**
|
||||
* Return the device this PHY is associated with
|
||||
*
|
||||
* \return the device this PHY is associated with
|
||||
*/
|
||||
Ptr<NetDevice> GetDevice (void) const;
|
||||
/**
|
||||
* Return the mobility model this PHY is associated with.
|
||||
* This method will return either the mobility model that has been
|
||||
* explicitly set by a call to SpectrumWifiPhy::SetMobility(), or else
|
||||
* will return the mobility model (if any) that has been aggregated
|
||||
* to the node.
|
||||
*
|
||||
* \return the mobility model this PHY is associated with
|
||||
*/
|
||||
Ptr<MobilityModel> GetMobility (void);
|
||||
/**
|
||||
* Return the minimum available transmission power level (dBm).
|
||||
* \return the minimum available transmission power level (dBm)
|
||||
*/
|
||||
virtual double GetTxPowerStart (void) const;
|
||||
/**
|
||||
* Return the maximum available transmission power level (dBm).
|
||||
* \return the maximum available transmission power level (dBm)
|
||||
*/
|
||||
virtual double GetTxPowerEnd (void) const;
|
||||
/**
|
||||
* Return the number of available transmission power levels.
|
||||
*
|
||||
* \return the number of available transmission power levels
|
||||
*/
|
||||
virtual uint32_t GetNTxPower (void) const;
|
||||
|
||||
/**
|
||||
* Input method for delivering a signal from the spectrum channel
|
||||
* and low-level Phy interface to this SpectrumWifiPhy instance.
|
||||
*
|
||||
* \param rxParams Input signal parameters
|
||||
*/
|
||||
void StartRx (Ptr<SpectrumSignalParameters> rxParams);
|
||||
/**
|
||||
* Method to encapsulate the creation of the WifiSpectrumPhyInterface
|
||||
* object (used to bind the WifiSpectrumPhy to a SpectrumChannel) and
|
||||
* to link it to this SpectrumWifiPhy instance
|
||||
*
|
||||
* \param device pointer to the NetDevice object including this new object
|
||||
*/
|
||||
void CreateWifiSpectrumPhyInterface (Ptr<NetDevice> device);
|
||||
/**
|
||||
* \return pointer to WifiSpectrumPhyInterface associated with this Phy
|
||||
*/
|
||||
Ptr<WifiSpectrumPhyInterface> GetSpectrumPhy (void) const;
|
||||
/**
|
||||
* \param antenna an AntennaModel to include in the transmitted
|
||||
* SpectrumSignalParameters (in case any objects downstream of the
|
||||
* SpectrumWifiPhy wish to adjust signal properties based on the
|
||||
* transmitted antenna model. This antenna is also used when
|
||||
* the underlying WifiSpectrumPhyInterface::GetRxAntenna() method
|
||||
* is called.
|
||||
*
|
||||
* Note: this method may be split into separate SetTx and SetRx
|
||||
* methods in the future if the modelling need for this arises
|
||||
*/
|
||||
void SetAntenna (Ptr<AntennaModel> antenna);
|
||||
/**
|
||||
* Get the antenna model used for reception
|
||||
*
|
||||
* \return the AntennaModel used for reception
|
||||
*/
|
||||
Ptr<AntennaModel> GetRxAntenna (void) const;
|
||||
/**
|
||||
* \return returns the SpectrumModel that this SpectrumPhy expects to be used
|
||||
* for all SpectrumValues that are passed to StartRx. If 0 is
|
||||
* returned, it means that any model will be accepted.
|
||||
*/
|
||||
Ptr<const SpectrumModel> GetRxSpectrumModel () const;
|
||||
/**
|
||||
* Callback invoked at the end of a frame reception, to notify whether
|
||||
* the frame was received successfully (true) or not (false)
|
||||
*/
|
||||
typedef Callback<void,bool> RxCallback;
|
||||
/**
|
||||
* Set the packet received callback (invoked at the end of a frame
|
||||
* reception), to notify whether the frame was received successfully
|
||||
* or not.
|
||||
*
|
||||
* \param callback the function to hook to the callback
|
||||
*/
|
||||
void SetPacketReceivedCallback (RxCallback callback);
|
||||
|
||||
/**
|
||||
* Callback invoked when the Phy model starts to process a signal
|
||||
*
|
||||
* \param signalType Whether signal is WiFi (true) or foreign (false)
|
||||
* \param senderNodeId Node Id of the sender of the signal
|
||||
* \param rxPower received signal power (dBm)
|
||||
* \param duration Signal duration
|
||||
*/
|
||||
typedef void (* SignalArrivalCallback) (bool signalType, uint32_t senderNodeId, double rxPower, Time duration);
|
||||
|
||||
virtual void SetReceiveOkCallback (WifiPhy::RxOkCallback callback);
|
||||
virtual void SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback);
|
||||
virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, enum WifiPreamble preamble);
|
||||
virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, enum WifiPreamble preamble, enum mpduType mpdutype);
|
||||
virtual void RegisterListener (WifiPhyListener *listener);
|
||||
virtual void UnregisterListener (WifiPhyListener *listener);
|
||||
virtual void SetSleepMode (void);
|
||||
virtual void ResumeFromSleep (void);
|
||||
virtual bool IsStateCcaBusy (void);
|
||||
virtual bool IsStateIdle (void);
|
||||
virtual bool IsStateBusy (void);
|
||||
virtual bool IsStateRx (void);
|
||||
virtual bool IsStateTx (void);
|
||||
virtual bool IsStateSwitching (void);
|
||||
virtual bool IsStateSleep (void);
|
||||
virtual Time GetStateDuration (void);
|
||||
virtual Time GetDelayUntilIdle (void);
|
||||
virtual Time GetLastRxStartTime (void) const;
|
||||
virtual uint32_t GetNModes (void) const;
|
||||
virtual WifiMode GetMode (uint32_t mode) const;
|
||||
virtual bool IsModeSupported (WifiMode mode) const;
|
||||
virtual bool IsMcsSupported (WifiMode mcs);
|
||||
virtual double CalculateSnr (WifiTxVector txVector, double ber) const;
|
||||
virtual Ptr<WifiChannel> GetChannel (void) const;
|
||||
|
||||
virtual void ConfigureStandard (enum WifiPhyStandard standard);
|
||||
|
||||
/**
|
||||
* Assign a fixed random variable stream number to the random variables
|
||||
* used by this model. Return the number of streams (possibly zero) that
|
||||
* have been assigned.
|
||||
*
|
||||
* \param stream first stream index to use
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
int64_t AssignStreams (int64_t stream);
|
||||
|
||||
/**
|
||||
* \param tx the number of transmitters on this node.
|
||||
*/
|
||||
virtual void SetNumberOfTransmitAntennas (uint32_t tx);
|
||||
/**
|
||||
* \return the number of transmitters on this node.
|
||||
*/
|
||||
virtual uint32_t GetNumberOfTransmitAntennas (void) const;
|
||||
/**
|
||||
* \param rx the number of receivers on this node.
|
||||
*/
|
||||
virtual void SetNumberOfReceiveAntennas (uint32_t rx);
|
||||
/**
|
||||
* \return the number of receivers on this node.
|
||||
*/
|
||||
virtual uint32_t GetNumberOfReceiveAntennas (void) const;
|
||||
/**
|
||||
* Enable or disable short/long guard interval.
|
||||
*
|
||||
* \param guardInterval Enable or disable guard interval
|
||||
*/
|
||||
virtual void SetGuardInterval (bool guardInterval);
|
||||
/**
|
||||
* Return whether guard interval is being used.
|
||||
*
|
||||
* \return true if guard interval is being used, false otherwise
|
||||
*/
|
||||
virtual bool GetGuardInterval (void) const;
|
||||
/**
|
||||
* Enable or disable LDPC.
|
||||
* \param ldpc Enable or disable LDPC
|
||||
*/
|
||||
virtual void SetLdpc (bool ldpc);
|
||||
/**
|
||||
* Return if LDPC is supported.
|
||||
*
|
||||
* \return true if LDPC is supported, false otherwise
|
||||
*/
|
||||
virtual bool GetLdpc (void) const;
|
||||
/**
|
||||
* Enable or disable STBC.
|
||||
*
|
||||
* \param stbc Enable or disable STBC
|
||||
*/
|
||||
virtual void SetStbc (bool stbc);
|
||||
/**
|
||||
* Return whether STBC is supported.
|
||||
*
|
||||
* \return true if STBC is supported, false otherwise
|
||||
*/
|
||||
virtual bool GetStbc (void) const;
|
||||
/**
|
||||
* Enable or disable Greenfield support.
|
||||
*
|
||||
* \param greenfield Enable or disable Greenfield
|
||||
*/
|
||||
virtual void SetGreenfield (bool greenfield);
|
||||
/**
|
||||
* Return whether Greenfield is supported.
|
||||
*
|
||||
* \return true if Greenfield is supported, false otherwise
|
||||
*/
|
||||
virtual bool GetGreenfield (void) const;
|
||||
/**
|
||||
* Enable or disable short PLCP preamble.
|
||||
*
|
||||
* \param preamble sets whether short PLCP preamble is supported or not
|
||||
*/
|
||||
virtual void SetShortPlcpPreambleSupported (bool preamble);
|
||||
/**
|
||||
* Return whether short PLCP preamble is supported.
|
||||
*
|
||||
* \returns if short PLCP preamble is supported or not
|
||||
*/
|
||||
virtual bool GetShortPlcpPreambleSupported (void) const;
|
||||
|
||||
virtual uint8_t GetSupportedRxSpatialStreams (void) const;
|
||||
virtual uint8_t GetSupportedTxSpatialStreams (void) const;
|
||||
virtual uint32_t GetNBssMembershipSelectors (void) const;
|
||||
virtual uint32_t GetBssMembershipSelector (uint32_t selector) const;
|
||||
virtual WifiModeList GetMembershipSelectorModes (uint32_t selector);
|
||||
|
||||
/**
|
||||
* \return the number of MCS supported by this phy
|
||||
*/
|
||||
virtual uint8_t GetNMcs (void) const;
|
||||
virtual WifiMode GetMcs (uint8_t mcs) const;
|
||||
|
||||
protected:
|
||||
// Inherited
|
||||
virtual void DoDispose (void);
|
||||
virtual void DoInitialize (void);
|
||||
virtual bool DoChannelSwitch (uint16_t id);
|
||||
virtual bool DoFrequencySwitch (uint32_t frequency);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Configure SpectrumWifiPhy with appropriate channel frequency and
|
||||
* supported rates for 802.11a standard.
|
||||
*/
|
||||
void Configure80211a (void);
|
||||
/**
|
||||
* Configure SpectrumWifiPhy with appropriate channel frequency and
|
||||
* supported rates for 802.11b standard.
|
||||
*/
|
||||
void Configure80211b (void);
|
||||
/**
|
||||
* Configure SpectrumWifiPhy with appropriate channel frequency and
|
||||
* supported rates for 802.11g standard.
|
||||
*/
|
||||
void Configure80211g (void);
|
||||
/**
|
||||
* Configure SpectrumWifiPhy with appropriate channel frequency and
|
||||
* supported rates for 802.11a standard with 10MHz channel spacing.
|
||||
*/
|
||||
void Configure80211_10Mhz (void);
|
||||
/**
|
||||
* Configure SpectrumWifiPhy with appropriate channel frequency and
|
||||
* supported rates for 802.11a standard with 5MHz channel spacing.
|
||||
*/
|
||||
void Configure80211_5Mhz ();
|
||||
void ConfigureHolland (void);
|
||||
/**
|
||||
* Configure SpectrumWifiPhy with appropriate channel frequency and
|
||||
* supported rates for 802.11n standard.
|
||||
*/
|
||||
void Configure80211n (void);
|
||||
/**
|
||||
* Configure SpectrumWifiPhy with appropriate channel frequency and
|
||||
* supported rates for 802.11ac standard.
|
||||
*/
|
||||
void Configure80211ac (void);
|
||||
/**
|
||||
* Configure the device Mcs set with the appropriate HtMcs modes for
|
||||
* the number of available transmit spatial streams
|
||||
*/
|
||||
void ConfigureHtDeviceMcsSet (void);
|
||||
/**
|
||||
* Return the energy detection threshold.
|
||||
*
|
||||
* \return the energy detection threshold.
|
||||
*/
|
||||
double GetEdThresholdW (void) const;
|
||||
/**
|
||||
* Convert from dBm to Watts.
|
||||
*
|
||||
* \param dbm the power in dBm
|
||||
*
|
||||
* \return the equivalent Watts for the given dBm
|
||||
*/
|
||||
double DbmToW (double dbm) const;
|
||||
/**
|
||||
* Convert from dB to ratio.
|
||||
*
|
||||
* \param db
|
||||
*
|
||||
* \return ratio
|
||||
*/
|
||||
double DbToRatio (double db) const;
|
||||
/**
|
||||
* Convert from Watts to dBm.
|
||||
*
|
||||
* \param w the power in Watts
|
||||
*
|
||||
* \return the equivalent dBm for the given Watts
|
||||
*/
|
||||
double WToDbm (double w) const;
|
||||
/**
|
||||
* Convert from ratio to dB.
|
||||
*
|
||||
* \param ratio
|
||||
*
|
||||
* \return dB
|
||||
*/
|
||||
double RatioToDb (double ratio) const;
|
||||
/**
|
||||
* Get the power of the given power level in dBm.
|
||||
* In SpectrumWifiPhy implementation, the power levels are equally spaced (in dBm).
|
||||
*
|
||||
* \param power the power level
|
||||
*
|
||||
* \return the transmission power in dBm at the given power level
|
||||
*/
|
||||
double GetPowerDbm (uint8_t power) const;
|
||||
/**
|
||||
* 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 mpdutype the type of the MPDU as defined in WifiPhy::mpduType.
|
||||
* \param event the corresponding event of the first time the packet arrives
|
||||
*/
|
||||
void EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, enum mpduType mpdutype, Ptr<InterferenceHelper::Event> event);
|
||||
|
||||
/**
|
||||
* Check if Phy state should move to CCA busy state based on current
|
||||
* state of interference tracker. In this model, CCA becomes busy when
|
||||
* the aggregation of all signals as tracked by the InterferenceHelper
|
||||
* class is higher than the CcaMode1Threshold
|
||||
*/
|
||||
void SwitchMaybeToCcaBusy (void);
|
||||
|
||||
/**
|
||||
* \param centerFrequency center frequency (MHz)
|
||||
* \param channelWidth channel width (MHz) of the channel
|
||||
* \param txPowerW power in W to spread across the bands
|
||||
* \return Ptr to SpectrumValue
|
||||
*
|
||||
* This is a helper function to create the right Tx PSD corresponding
|
||||
* to the standard in use.
|
||||
*/
|
||||
Ptr<SpectrumValue> GetTxPowerSpectralDensity (uint32_t centerFrequency, uint32_t channelWidth, double txPowerW) const;
|
||||
|
||||
double m_edThresholdW; //!< Energy detection threshold in watts
|
||||
double m_ccaMode1ThresholdW; //!< Clear channel assessment (CCA) threshold in watts
|
||||
double m_txGainDb; //!< Transmission gain (dB)
|
||||
double m_rxGainDb; //!< Reception gain (dB)
|
||||
double m_txPowerBaseDbm; //!< Minimum transmission power (dBm)
|
||||
double m_txPowerEndDbm; //!< Maximum transmission power (dBm)
|
||||
uint32_t m_nTxPower; //!< Number of available transmission power levels
|
||||
|
||||
Ptr<SpectrumChannel> m_channel; //!< SpectrumChannel that this SpectrumWifiPhy is connected to
|
||||
std::vector<uint16_t> m_operationalChannelList; //!< List of possible channels
|
||||
Ptr<NetDevice> m_device; //!< Pointer to the device
|
||||
Ptr<MobilityModel> m_mobility; //!< Pointer to the mobility model
|
||||
|
||||
uint32_t m_numberOfTransmitters; //!< Number of transmitters
|
||||
uint32_t m_numberOfReceivers; //!< Number of receivers
|
||||
bool m_ldpc; //!< Flag if LDPC is used
|
||||
bool m_stbc; //!< Flag if STBC is used
|
||||
bool m_greenfield; //!< Flag if GreenField format is supported
|
||||
bool m_guardInterval; //!< Flag if short guard interval is used
|
||||
bool m_shortPreamble; //!< Flag if short PLCP preamble is supported
|
||||
|
||||
/**
|
||||
* This vector holds the set of transmission modes that this
|
||||
* WifiPhy(-derived class) can support. In conversation we call this
|
||||
* the DeviceRateSet (not a term you'll find in the standard), and
|
||||
* it is a superset of standard-defined parameters such as the
|
||||
* OperationalRateSet, and the BSSBasicRateSet (which, themselves,
|
||||
* have a superset/subset relationship).
|
||||
*
|
||||
* Mandatory rates relevant to this WifiPhy can be found by
|
||||
* iterating over this vector looking for WifiMode objects for which
|
||||
* WifiMode::IsMandatory() is true.
|
||||
*
|
||||
* A quick note is appropriate here (well, here is as good a place
|
||||
* as any I can find)...
|
||||
*
|
||||
* In the standard there is no text that explicitly precludes
|
||||
* production of a device that does not support some rates that are
|
||||
* mandatory (according to the standard) for PHYs that the device
|
||||
* happens to fully or partially support.
|
||||
*
|
||||
* This approach is taken by some devices which choose to only support,
|
||||
* for example, 6 and 9 Mbps ERP-OFDM rates for cost and power
|
||||
* consumption reasons (i.e., these devices don't need to be designed
|
||||
* for and waste current on the increased linearity requirement of
|
||||
* higher-order constellations when 6 and 9 Mbps more than meet their
|
||||
* data requirements). The wording of the standard allows such devices
|
||||
* to have an OperationalRateSet which includes 6 and 9 Mbps ERP-OFDM
|
||||
* rates, despite 12 and 24 Mbps being "mandatory" rates for the
|
||||
* ERP-OFDM PHY.
|
||||
*
|
||||
* Now this doesn't actually have any impact on code, yet. It is,
|
||||
* however, something that we need to keep in mind for the
|
||||
* future. Basically, the key point is that we can't be making
|
||||
* assumptions like "the Operational Rate Set will contain all the
|
||||
* mandatory rates".
|
||||
*/
|
||||
WifiModeList m_deviceRateSet;
|
||||
WifiModeList m_deviceMcsSet;
|
||||
|
||||
std::vector<uint32_t> m_bssMembershipSelectorSet;
|
||||
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
|
||||
Ptr<WifiPhyStateHelper> m_state; //!< Pointer to WifiPhyStateHelper
|
||||
InterferenceHelper m_interference; //!< Pointer to InterferenceHelper
|
||||
Ptr<WifiSpectrumPhyInterface> m_wifiSpectrumPhyInterface;
|
||||
Ptr<AntennaModel> m_antenna;
|
||||
mutable Ptr<const SpectrumModel> m_rxSpectrumModel;
|
||||
RxCallback m_rxCallback;
|
||||
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
|
||||
uint32_t m_txMpduReferenceNumber; //!< A-MPDU reference number to identify all transmitted subframes belonging to the same received A-MPDU
|
||||
uint32_t m_rxMpduReferenceNumber; //!< A-MPDU reference number to identify all received subframes belonging to the same received A-MPDU
|
||||
bool m_disableWifiReception; //!< forces this Phy to fail to sync on any signal
|
||||
TracedCallback<bool, uint32_t, double, Time> m_signalCb;
|
||||
|
||||
};
|
||||
|
||||
} //namespace ns3
|
||||
|
||||
#endif /* SPECTRUM_WIFI_PHY_H */
|
||||
@@ -209,6 +209,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class WifiModeFactory;
|
||||
friend class WifiPhyTag; // access the UID-based constructor
|
||||
/**
|
||||
* Create a WifiMode from a given unique ID.
|
||||
*
|
||||
|
||||
107
src/wifi/model/wifi-phy-tag.cc
Normal file
107
src/wifi/model/wifi-phy-tag.cc
Normal file
@@ -0,0 +1,107 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 CTTC
|
||||
*
|
||||
* 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: Nicola Baldo <nbaldo@cttc.es>
|
||||
*/
|
||||
#include <ns3/wifi-phy-tag.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
TypeId
|
||||
WifiPhyTag::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::WifiPhyTag")
|
||||
.SetParent<Tag> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
WifiPhyTag::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
WifiPhyTag::GetSerializedSize (void) const
|
||||
{
|
||||
return (4 + (6 * 1) + 4 + 2);
|
||||
}
|
||||
|
||||
void
|
||||
WifiPhyTag::Serialize (TagBuffer i) const
|
||||
{
|
||||
i.WriteU32 (m_wifiTxVector.GetMode ().GetUid ());
|
||||
i.WriteU8 (m_wifiTxVector.GetTxPowerLevel ());
|
||||
i.WriteU8 (m_wifiTxVector.GetRetries ());
|
||||
i.WriteU8 (m_wifiTxVector.IsShortGuardInterval ());
|
||||
i.WriteU8 (m_wifiTxVector.GetNss ());
|
||||
i.WriteU8 (m_wifiTxVector.GetNess ());
|
||||
i.WriteU8 (m_wifiTxVector.IsStbc ());
|
||||
i.WriteU32 (m_wifiPreamble);
|
||||
i.WriteU16 (m_mpduType);
|
||||
}
|
||||
|
||||
void
|
||||
WifiPhyTag::Deserialize (TagBuffer i)
|
||||
{
|
||||
m_wifiTxVector.SetMode (WifiMode (i.ReadU32 ()));
|
||||
m_wifiTxVector.SetTxPowerLevel (i.ReadU8 ());
|
||||
m_wifiTxVector.SetRetries (i.ReadU8 ());
|
||||
m_wifiTxVector.SetShortGuardInterval (i.ReadU8 ());
|
||||
m_wifiTxVector.SetNss (i.ReadU8 ());
|
||||
m_wifiTxVector.SetNess (i.ReadU8 ());
|
||||
m_wifiTxVector.SetStbc (i.ReadU8 ());
|
||||
m_wifiPreamble = i.ReadU32 ();
|
||||
m_mpduType = static_cast<enum mpduType> (i.ReadU16 ());
|
||||
}
|
||||
void
|
||||
WifiPhyTag::Print (std::ostream &os) const
|
||||
{
|
||||
os << m_wifiTxVector << " " << (m_wifiPreamble ? "SP " : "LP ") << m_mpduType;
|
||||
}
|
||||
|
||||
WifiPhyTag::WifiPhyTag ()
|
||||
{
|
||||
}
|
||||
|
||||
WifiPhyTag::WifiPhyTag (WifiTxVector txVector, WifiPreamble preamble, enum mpduType mpdutype)
|
||||
: m_wifiTxVector (txVector),
|
||||
m_wifiPreamble (preamble),
|
||||
m_mpduType (mpdutype)
|
||||
{
|
||||
}
|
||||
|
||||
WifiTxVector
|
||||
WifiPhyTag::GetWifiTxVector (void) const
|
||||
{
|
||||
return m_wifiTxVector;
|
||||
}
|
||||
|
||||
WifiPreamble
|
||||
WifiPhyTag::GetWifiPreamble (void) const
|
||||
{
|
||||
return ((enum WifiPreamble) m_wifiPreamble);
|
||||
}
|
||||
|
||||
enum mpduType
|
||||
WifiPhyTag::GetMpduType (void) const
|
||||
{
|
||||
return m_mpduType;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
83
src/wifi/model/wifi-phy-tag.h
Normal file
83
src/wifi/model/wifi-phy-tag.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 CTTC
|
||||
*
|
||||
* 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: Nicola Baldo <nbaldo@cttc.es>
|
||||
*/
|
||||
#ifndef WIFI_PHY_TAG_H
|
||||
#define WIFI_PHY_TAG_H
|
||||
|
||||
#include <ns3/tag.h>
|
||||
#include <ns3/wifi-tx-vector.h>
|
||||
#include <ns3/wifi-preamble.h>
|
||||
#include <ns3/wifi-phy.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \ingroup wifi
|
||||
*
|
||||
* Tag for WifiTxVector and WifiPreamble information to be embedded in outgoing
|
||||
* transmissions as a PacketTag
|
||||
*/
|
||||
class WifiPhyTag : public Tag
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
WifiPhyTag ();
|
||||
/**
|
||||
* Constructor
|
||||
* \param txVector the WifiTxVector
|
||||
* \param preamble the WifiPreamble
|
||||
* \param mpduType the mpduType
|
||||
*/
|
||||
WifiPhyTag (WifiTxVector txVector, WifiPreamble preamble, enum mpduType mpdutype);
|
||||
/**
|
||||
* Getter for WifiTxVector parameter
|
||||
* \return the WifiTxVector
|
||||
*/
|
||||
WifiTxVector GetWifiTxVector (void) const;
|
||||
/**
|
||||
* Getter for WifiPreamble parameter
|
||||
* \return preamble the WifiPreamble
|
||||
*/
|
||||
WifiPreamble GetWifiPreamble (void) const;
|
||||
/**
|
||||
* Getter for mpduType parameter
|
||||
* \return mpduType the mpduType
|
||||
*/
|
||||
enum mpduType GetMpduType (void) const;
|
||||
|
||||
// From class Tag
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
virtual void Serialize (TagBuffer i) const;
|
||||
virtual void Deserialize (TagBuffer i);
|
||||
virtual void Print (std::ostream &os) const;
|
||||
|
||||
private:
|
||||
WifiTxVector m_wifiTxVector;
|
||||
int32_t m_wifiPreamble;
|
||||
enum mpduType m_mpduType;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* WIFI_PHY_TAG_H */
|
||||
@@ -474,7 +474,7 @@ WifiPhy::SetFrequency (uint32_t frequency)
|
||||
m_channelCenterFrequency = frequency;
|
||||
m_channelNumber = nch;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Suppressing reassignment of frequency");
|
||||
}
|
||||
|
||||
117
src/wifi/model/wifi-spectrum-phy-interface.cc
Normal file
117
src/wifi/model/wifi-spectrum-phy-interface.cc
Normal file
@@ -0,0 +1,117 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 CTTC
|
||||
*
|
||||
* 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: Nicola Baldo <nbaldo@cttc.es>
|
||||
*/
|
||||
|
||||
#include <ns3/ptr.h>
|
||||
#include <ns3/object.h>
|
||||
#include <ns3/net-device.h>
|
||||
#include <ns3/mobility-model.h>
|
||||
#include <ns3/wifi-phy.h>
|
||||
#include <ns3/spectrum-phy.h>
|
||||
#include <ns3/spectrum-signal-parameters.h>
|
||||
#include <ns3/log.h>
|
||||
#include <ns3/spectrum-value.h>
|
||||
#include <ns3/antenna-model.h>
|
||||
|
||||
#include "wifi-spectrum-phy-interface.h"
|
||||
#include "spectrum-wifi-phy.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("WifiSpectrumPhyInterface");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (WifiSpectrumPhyInterface);
|
||||
|
||||
TypeId
|
||||
WifiSpectrumPhyInterface::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::WifiSpectrumPhyInterface")
|
||||
.SetParent<SpectrumPhy> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
WifiSpectrumPhyInterface::WifiSpectrumPhyInterface ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
WifiSpectrumPhyInterface::DoDispose (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_spectrumWifiPhy = 0;
|
||||
}
|
||||
|
||||
void WifiSpectrumPhyInterface::SetSpectrumWifiPhy (Ptr<SpectrumWifiPhy> spectrumWifiPhy)
|
||||
{
|
||||
m_spectrumWifiPhy = spectrumWifiPhy;
|
||||
}
|
||||
|
||||
Ptr<NetDevice>
|
||||
WifiSpectrumPhyInterface::GetDevice () const
|
||||
{
|
||||
return m_netDevice;
|
||||
}
|
||||
|
||||
Ptr<MobilityModel>
|
||||
WifiSpectrumPhyInterface::GetMobility ()
|
||||
{
|
||||
return m_spectrumWifiPhy->GetMobility ();
|
||||
}
|
||||
|
||||
void
|
||||
WifiSpectrumPhyInterface::SetDevice (Ptr<NetDevice> d)
|
||||
{
|
||||
m_netDevice = d;
|
||||
}
|
||||
|
||||
void
|
||||
WifiSpectrumPhyInterface::SetMobility (Ptr<MobilityModel> m)
|
||||
{
|
||||
m_spectrumWifiPhy->SetMobility (m);
|
||||
}
|
||||
|
||||
void
|
||||
WifiSpectrumPhyInterface::SetChannel (Ptr<SpectrumChannel> c)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << c);
|
||||
m_channel = c;
|
||||
}
|
||||
|
||||
Ptr<const SpectrumModel>
|
||||
WifiSpectrumPhyInterface::GetRxSpectrumModel () const
|
||||
{
|
||||
return m_spectrumWifiPhy->GetRxSpectrumModel ();
|
||||
}
|
||||
|
||||
Ptr<AntennaModel>
|
||||
WifiSpectrumPhyInterface::GetRxAntenna (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_spectrumWifiPhy->GetRxAntenna ();
|
||||
}
|
||||
|
||||
void
|
||||
WifiSpectrumPhyInterface::StartRx (Ptr<SpectrumSignalParameters> params)
|
||||
{
|
||||
m_spectrumWifiPhy->StartRx (params);
|
||||
}
|
||||
|
||||
|
||||
} //namespace ns3
|
||||
72
src/wifi/model/wifi-spectrum-phy-interface.h
Normal file
72
src/wifi/model/wifi-spectrum-phy-interface.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 CTTC
|
||||
*
|
||||
* 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: Nicola Baldo <nbaldo@cttc.es>
|
||||
*/
|
||||
#ifndef WIFI_SPECTRUM_PHY_INTERFACE_H
|
||||
#define WIFI_SPECTRUM_PHY_INTERFACE_H
|
||||
|
||||
#include <ns3/ptr.h>
|
||||
#include <ns3/object.h>
|
||||
#include <ns3/spectrum-phy.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class SpectrumWifiPhy;
|
||||
|
||||
/**
|
||||
* \ingroup wifi
|
||||
*
|
||||
* This class is an adaptor between class SpectrumWifiPhy (which inherits
|
||||
* from WifiPhy) and class SpectrumChannel (which expects objects derived
|
||||
* from class SpectrumPhy to be connected to it).
|
||||
*
|
||||
* The adaptor is used only in the receive direction; in the transmit
|
||||
* direction, the class SpectrumWifiPhy constructs signal parameters
|
||||
* and directly accesses the SpectrumChannel
|
||||
*/
|
||||
class WifiSpectrumPhyInterface : public SpectrumPhy
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
WifiSpectrumPhyInterface ();
|
||||
/**
|
||||
* Connect SpectrumWifiPhy object
|
||||
* \param phy SpectrumWifiPhy object to be connected to this object
|
||||
*/
|
||||
void SetSpectrumWifiPhy (Ptr<SpectrumWifiPhy> phy);
|
||||
|
||||
// Inherited from SpectrumPhy
|
||||
virtual Ptr<NetDevice> GetDevice () const;
|
||||
virtual void SetDevice (Ptr<NetDevice> d);
|
||||
virtual void SetMobility (Ptr<MobilityModel> m);
|
||||
virtual Ptr<MobilityModel> GetMobility ();
|
||||
virtual void SetChannel (Ptr<SpectrumChannel> c);
|
||||
virtual Ptr<const SpectrumModel> GetRxSpectrumModel () const;
|
||||
virtual Ptr<AntennaModel> GetRxAntenna ();
|
||||
virtual void StartRx (Ptr<SpectrumSignalParameters> params);
|
||||
|
||||
private:
|
||||
virtual void DoDispose (void);
|
||||
Ptr<SpectrumWifiPhy> m_spectrumWifiPhy;
|
||||
Ptr<NetDevice> m_netDevice;
|
||||
Ptr<SpectrumChannel> m_channel;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* WIFI_SPECTRUM_PHY_INTERFACE_H */
|
||||
58
src/wifi/model/wifi-spectrum-signal-parameters.cc
Normal file
58
src/wifi/model/wifi-spectrum-signal-parameters.cc
Normal file
@@ -0,0 +1,58 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 CTTC
|
||||
*
|
||||
* 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: Nicola Baldo <nbaldo@cttc.es>
|
||||
* Modified by Marco Miozzo <mmiozzo@cttc.es> (add data and ctrl diversity)
|
||||
*/
|
||||
|
||||
#include <ns3/log.h>
|
||||
#include <ns3/packet.h>
|
||||
#include <ns3/ptr.h>
|
||||
#include "wifi-spectrum-signal-parameters.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("WifiSpectrumSignalParameters");
|
||||
|
||||
WifiSpectrumSignalParameters::WifiSpectrumSignalParameters ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
WifiSpectrumSignalParameters::WifiSpectrumSignalParameters (const WifiSpectrumSignalParameters& p)
|
||||
: SpectrumSignalParameters (p)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << &p);
|
||||
packet = p.packet;
|
||||
}
|
||||
|
||||
Ptr<SpectrumSignalParameters>
|
||||
WifiSpectrumSignalParameters::Copy ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
// Ideally we would use:
|
||||
// return Copy<WifiSpectrumSignalParameters> (*this);
|
||||
// but for some reason it doesn't work. Another alternative is
|
||||
// return Copy<WifiSpectrumSignalParameters> (this);
|
||||
// but it causes a double creation of the object, hence it is less efficient.
|
||||
// The solution below is copied from the implementation of Copy<> (Ptr<>) in ptr.h
|
||||
Ptr<WifiSpectrumSignalParameters> wssp (new WifiSpectrumSignalParameters (*this), false);
|
||||
return wssp;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
60
src/wifi/model/wifi-spectrum-signal-parameters.h
Normal file
60
src/wifi/model/wifi-spectrum-signal-parameters.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 CTTC
|
||||
*
|
||||
* 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: Nicola Baldo <nbaldo@cttc.es>
|
||||
* Modified by Marco Miozzo <mmiozzo@cttc.es> (add data and ctrl diversity)
|
||||
*/
|
||||
|
||||
#ifndef WIFI_SPECTRUM_SIGNAL_PARAMETERS_H
|
||||
#define WIFI_SPECTRUM_SIGNAL_PARAMETERS_H
|
||||
|
||||
#include <ns3/spectrum-signal-parameters.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Packet;
|
||||
|
||||
/**
|
||||
* \ingroup wifi
|
||||
*
|
||||
* Signal parameters for wifi
|
||||
*/
|
||||
struct WifiSpectrumSignalParameters : public SpectrumSignalParameters
|
||||
{
|
||||
|
||||
// inherited from SpectrumSignalParameters
|
||||
virtual Ptr<SpectrumSignalParameters> Copy ();
|
||||
|
||||
/**
|
||||
* default constructor
|
||||
*/
|
||||
WifiSpectrumSignalParameters ();
|
||||
|
||||
/**
|
||||
* copy constructor
|
||||
*/
|
||||
WifiSpectrumSignalParameters (const WifiSpectrumSignalParameters& p);
|
||||
|
||||
/**
|
||||
* The packet being transmitted with this signal
|
||||
*/
|
||||
Ptr<Packet> packet;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* WIFI_SPECTRUM_SIGNAL_PARAMETERS_H */
|
||||
261
src/wifi/test/spectrum-wifi-phy-test.cc
Normal file
261
src/wifi/test/spectrum-wifi-phy-test.cc
Normal file
@@ -0,0 +1,261 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015 University of Washington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/tag.h"
|
||||
#include "ns3/packet-burst.h"
|
||||
#include "ns3/spectrum-wifi-helper.h"
|
||||
#include "ns3/wifi-spectrum-value-helper.h"
|
||||
#include "ns3/spectrum-wifi-phy.h"
|
||||
#include "ns3/interference-helper.h"
|
||||
#include "ns3/nist-error-rate-model.h"
|
||||
#include "ns3/wifi-mac-header.h"
|
||||
#include "ns3/wifi-mac-trailer.h"
|
||||
#include "ns3/wifi-phy-tag.h"
|
||||
#include "ns3/wifi-phy-standard.h"
|
||||
#include "ns3/wifi-spectrum-signal-parameters.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
static const uint16_t CHANNEL_NUMBER = 36;
|
||||
static const uint32_t FREQUENCY = 5180; // MHz
|
||||
static const uint32_t CHANNEL_WIDTH = 20; // MHz
|
||||
|
||||
class SpectrumWifiPhyBasicTest : public TestCase
|
||||
{
|
||||
public:
|
||||
SpectrumWifiPhyBasicTest ();
|
||||
SpectrumWifiPhyBasicTest (std::string name);
|
||||
virtual ~SpectrumWifiPhyBasicTest ();
|
||||
protected:
|
||||
virtual void DoSetup (void);
|
||||
Ptr<SpectrumWifiPhy> m_phy;
|
||||
Ptr<SpectrumSignalParameters> MakeSignal (double txPowerWatts);
|
||||
void SendSignal (double txPowerWatts);
|
||||
void SpectrumWifiPhyReceiver (bool rxSucceeded);
|
||||
uint32_t m_count;
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
SpectrumWifiPhyBasicTest::SpectrumWifiPhyBasicTest ()
|
||||
: TestCase ("SpectrumWifiPhy test case receives one packet"),
|
||||
m_count (0)
|
||||
{
|
||||
}
|
||||
|
||||
SpectrumWifiPhyBasicTest::SpectrumWifiPhyBasicTest (std::string name)
|
||||
: TestCase (name),
|
||||
m_count (0)
|
||||
{
|
||||
}
|
||||
|
||||
// Make a Wi-Fi signal to inject directly to the StartRx() method
|
||||
Ptr<SpectrumSignalParameters>
|
||||
SpectrumWifiPhyBasicTest::MakeSignal (double txPowerWatts)
|
||||
{
|
||||
WifiPreamble preamble;
|
||||
preamble = WIFI_PREAMBLE_LONG;
|
||||
WifiMode mode = WifiPhy::GetOfdmRate6Mbps ();
|
||||
WifiTxVector txVector = WifiTxVector (mode, 0, 0, false, 1, 0, 20000000, false, false);
|
||||
enum mpduType mpdutype = NORMAL_MPDU;
|
||||
|
||||
Ptr<Packet> pkt = Create<Packet> (1000);
|
||||
WifiMacHeader hdr;
|
||||
WifiMacTrailer trailer;
|
||||
|
||||
hdr.SetType (WIFI_MAC_QOSDATA);
|
||||
hdr.SetQosTid (0);
|
||||
uint32_t size = pkt->GetSize () + hdr.GetSize () + trailer.GetSerializedSize ();
|
||||
Time txDuration = m_phy->CalculateTxDuration (size, txVector, preamble, m_phy->GetFrequency(), mpdutype, 0);
|
||||
hdr.SetDuration (txDuration);
|
||||
|
||||
pkt->AddHeader (hdr);
|
||||
pkt->AddTrailer (trailer);
|
||||
WifiPhyTag tag (txVector, preamble, mpdutype);
|
||||
pkt->AddPacketTag (tag);
|
||||
Ptr<SpectrumValue> txPowerSpectrum = WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, txPowerWatts);
|
||||
Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
|
||||
txParams->psd = txPowerSpectrum;
|
||||
txParams->txPhy = 0;
|
||||
txParams->duration = txDuration;
|
||||
txParams->packet = pkt;
|
||||
return txParams;
|
||||
}
|
||||
|
||||
// Make a Wi-Fi signal to inject directly to the StartRx() method
|
||||
void
|
||||
SpectrumWifiPhyBasicTest::SendSignal (double txPowerWatts)
|
||||
{
|
||||
m_phy->StartRx (MakeSignal (txPowerWatts));
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyBasicTest::SpectrumWifiPhyReceiver (bool rxSucceeded)
|
||||
{
|
||||
m_count++;
|
||||
}
|
||||
|
||||
SpectrumWifiPhyBasicTest::~SpectrumWifiPhyBasicTest ()
|
||||
{
|
||||
}
|
||||
|
||||
// Create necessary objects, and inject signals. Test that the expected
|
||||
// number of packet receptions occur.
|
||||
void
|
||||
SpectrumWifiPhyBasicTest::DoSetup (void)
|
||||
{
|
||||
m_phy = CreateObject<SpectrumWifiPhy> ();
|
||||
m_phy->ConfigureStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
|
||||
Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
|
||||
m_phy->SetErrorRateModel (error);
|
||||
m_phy->SetChannelNumber (CHANNEL_NUMBER);
|
||||
m_phy->SetFrequency (FREQUENCY);
|
||||
m_phy->SetPacketReceivedCallback (MakeCallback (&SpectrumWifiPhyBasicTest::SpectrumWifiPhyReceiver, this));
|
||||
}
|
||||
|
||||
// Test that the expected number of packet receptions occur.
|
||||
void
|
||||
SpectrumWifiPhyBasicTest::DoRun (void)
|
||||
{
|
||||
double txPowerWatts = 0.010;
|
||||
// Send packets spaced 1 second apart; all should be received
|
||||
Simulator::Schedule (Seconds (1), &SpectrumWifiPhyBasicTest::SendSignal, this, txPowerWatts);
|
||||
Simulator::Schedule (Seconds (2), &SpectrumWifiPhyBasicTest::SendSignal, this, txPowerWatts);
|
||||
Simulator::Schedule (Seconds (3), &SpectrumWifiPhyBasicTest::SendSignal, this, txPowerWatts);
|
||||
// Send packets spaced 1 microsecond second apart; only one should be received
|
||||
Simulator::Schedule (MicroSeconds (4000000), &SpectrumWifiPhyBasicTest::SendSignal, this, txPowerWatts);
|
||||
Simulator::Schedule (MicroSeconds (4000001), &SpectrumWifiPhyBasicTest::SendSignal, this, txPowerWatts);
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (m_count, 4, "Didn't receive right number of packets");
|
||||
}
|
||||
|
||||
class TestPhyListener : public ns3::WifiPhyListener
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a test PhyListener
|
||||
*
|
||||
*/
|
||||
TestPhyListener (void) :
|
||||
m_notifyRxStart (0),
|
||||
m_notifyRxEndOk (0),
|
||||
m_notifyRxEndError (0),
|
||||
m_notifyMaybeCcaBusyStart (0)
|
||||
{
|
||||
}
|
||||
virtual ~TestPhyListener ()
|
||||
{
|
||||
}
|
||||
virtual void NotifyRxStart (Time duration)
|
||||
{
|
||||
++m_notifyRxStart;
|
||||
}
|
||||
virtual void NotifyRxEndOk (void)
|
||||
{
|
||||
++m_notifyRxEndOk;
|
||||
}
|
||||
virtual void NotifyRxEndError (void)
|
||||
{
|
||||
++m_notifyRxEndError;
|
||||
}
|
||||
virtual void NotifyTxStart (Time duration, double txPowerDbm)
|
||||
{
|
||||
}
|
||||
virtual void NotifyMaybeCcaBusyStart (Time duration)
|
||||
{
|
||||
++m_notifyMaybeCcaBusyStart;
|
||||
}
|
||||
virtual void NotifySwitchingStart (Time duration)
|
||||
{
|
||||
}
|
||||
virtual void NotifySleep (void)
|
||||
{
|
||||
}
|
||||
virtual void NotifyWakeup (void)
|
||||
{
|
||||
}
|
||||
uint32_t m_notifyRxStart;
|
||||
uint32_t m_notifyRxEndOk;
|
||||
uint32_t m_notifyRxEndError;
|
||||
uint32_t m_notifyMaybeCcaBusyStart;
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
class SpectrumWifiPhyListenerTest : public SpectrumWifiPhyBasicTest
|
||||
{
|
||||
public:
|
||||
SpectrumWifiPhyListenerTest ();
|
||||
virtual ~SpectrumWifiPhyListenerTest ();
|
||||
private:
|
||||
virtual void DoSetup (void);
|
||||
virtual void DoRun (void);
|
||||
TestPhyListener* m_listener;
|
||||
};
|
||||
|
||||
SpectrumWifiPhyListenerTest::SpectrumWifiPhyListenerTest ()
|
||||
: SpectrumWifiPhyBasicTest ("SpectrumWifiPhy test operation of WifiPhyListener")
|
||||
{
|
||||
}
|
||||
|
||||
SpectrumWifiPhyListenerTest::~SpectrumWifiPhyListenerTest ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyListenerTest::DoSetup (void)
|
||||
{
|
||||
SpectrumWifiPhyBasicTest::DoSetup ();
|
||||
m_listener = new TestPhyListener;
|
||||
m_phy->RegisterListener (m_listener);
|
||||
}
|
||||
|
||||
void
|
||||
SpectrumWifiPhyListenerTest::DoRun (void)
|
||||
{
|
||||
double txPowerWatts = 0.010;
|
||||
Simulator::Schedule (Seconds (1), &SpectrumWifiPhyListenerTest::SendSignal, this, txPowerWatts);
|
||||
Simulator::Run ();
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (m_count, 1, "Didn't receive right number of packets");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_listener->m_notifyRxStart, 1, "Didn't receive NotifyRxStart");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_listener->m_notifyRxEndOk, 1, "Didn't receive NotifyRxEnd");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_listener->m_notifyMaybeCcaBusyStart, 0, "Received NotifyMaybeCcaBusyStart unexpectedly");
|
||||
|
||||
Simulator::Destroy ();
|
||||
delete m_listener;
|
||||
}
|
||||
|
||||
class SpectrumWifiPhyTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
SpectrumWifiPhyTestSuite ();
|
||||
};
|
||||
|
||||
SpectrumWifiPhyTestSuite::SpectrumWifiPhyTestSuite ()
|
||||
: TestSuite ("spectrum-wifi-phy", UNIT)
|
||||
{
|
||||
AddTestCase (new SpectrumWifiPhyBasicTest, TestCase::QUICK);
|
||||
AddTestCase (new SpectrumWifiPhyListenerTest, TestCase::QUICK);
|
||||
}
|
||||
|
||||
static SpectrumWifiPhyTestSuite spectrumWifiPhyTestSuite;
|
||||
@@ -1,7 +1,7 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_ns3_module('wifi', ['network', 'propagation', 'energy'])
|
||||
obj = bld.create_ns3_module('wifi', ['network', 'propagation', 'energy', 'spectrum', 'antenna', 'mobility'])
|
||||
obj.source = [
|
||||
'model/wifi-information-element.cc',
|
||||
'model/wifi-information-element-vector.cc',
|
||||
@@ -17,6 +17,10 @@ def build(bld):
|
||||
'model/interference-helper.cc',
|
||||
'model/yans-wifi-phy.cc',
|
||||
'model/yans-wifi-channel.cc',
|
||||
'model/spectrum-wifi-phy.cc',
|
||||
'model/wifi-phy-tag.cc',
|
||||
'model/wifi-spectrum-phy-interface.cc',
|
||||
'model/wifi-spectrum-signal-parameters.cc',
|
||||
'model/wifi-mac-header.cc',
|
||||
'model/wifi-mac-trailer.cc',
|
||||
'model/mac-low.cc',
|
||||
@@ -81,6 +85,7 @@ def build(bld):
|
||||
'helper/athstats-helper.cc',
|
||||
'helper/wifi-helper.cc',
|
||||
'helper/yans-wifi-helper.cc',
|
||||
'helper/spectrum-wifi-helper.cc',
|
||||
'helper/nqos-wifi-mac-helper.cc',
|
||||
'helper/qos-wifi-mac-helper.cc',
|
||||
'helper/wifi-mac-helper.cc',
|
||||
@@ -93,6 +98,7 @@ def build(bld):
|
||||
'test/tx-duration-test.cc',
|
||||
'test/power-rate-adaptation-test.cc',
|
||||
'test/wifi-test.cc',
|
||||
'test/spectrum-wifi-phy-test.cc',
|
||||
'test/wifi-aggregation-test.cc',
|
||||
'test/wifi-error-rate-models-test.cc',
|
||||
]
|
||||
@@ -109,8 +115,12 @@ def build(bld):
|
||||
'model/wifi-preamble.h',
|
||||
'model/wifi-phy-standard.h',
|
||||
'model/yans-wifi-phy.h',
|
||||
'model/spectrum-wifi-phy.h',
|
||||
'model/wifi-phy-tag.h',
|
||||
'model/yans-wifi-channel.h',
|
||||
'model/wifi-phy.h',
|
||||
'model/wifi-spectrum-phy-interface.h',
|
||||
'model/wifi-spectrum-signal-parameters.h',
|
||||
'model/interference-helper.h',
|
||||
'model/wifi-remote-station-manager.h',
|
||||
'model/ap-wifi-mac.h',
|
||||
@@ -178,6 +188,7 @@ def build(bld):
|
||||
'helper/athstats-helper.h',
|
||||
'helper/wifi-helper.h',
|
||||
'helper/yans-wifi-helper.h',
|
||||
'helper/spectrum-wifi-helper.h',
|
||||
'helper/nqos-wifi-mac-helper.h',
|
||||
'helper/qos-wifi-mac-helper.h',
|
||||
'helper/wifi-mac-helper.h',
|
||||
|
||||
Reference in New Issue
Block a user