A Discrete-Event Network Simulator
API
wifi-trans-example.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Orange Labs
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Rediet <getachew.redieteab@orange.com>
18  */
19 
20 #include "ns3/command-line.h"
21 #include "ns3/gnuplot.h"
22 #include "ns3/mobility-helper.h"
23 #include "ns3/spectrum-analyzer-helper.h"
24 #include "ns3/spectrum-channel.h"
25 #include "ns3/spectrum-helper.h"
26 #include "ns3/spectrum-wifi-helper.h"
27 #include "ns3/ssid.h"
28 #include "ns3/string.h"
29 
30 using namespace ns3;
31 
46 void
47 SendPacket(Ptr<NetDevice> sourceDevice, Address& destination)
48 {
49  Ptr<Packet> pkt = Create<Packet>(100); // dummy bytes of data
50  sourceDevice->Send(pkt, destination, 0);
51 }
52 
53 int
54 main(int argc, char** argv)
55 {
56  std::string standard = "11a";
57  int bw = 20;
58  double pow = 23; // dBm
59  bool verbose = false;
60  CommandLine cmd(__FILE__);
61  cmd.AddValue("standard",
62  "OFDM-based Wi-Fi standard [11a, 11p_10MHZ, 11p_5MHZ, 11n_2_4GHZ, 11n_5GHZ, 11ac, "
63  "11ax_2_4GHZ, 11ax_5GHZ]",
64  standard);
65  cmd.AddValue("bw", "Bandwidth (consistent with standard, in MHz)", bw);
66  cmd.AddValue("txPower", "Transmit power (dBm)", pow);
67  cmd.AddValue("verbose",
68  "Display log messages for WifiSpectrumValueHelper and SpectrumWifiPhy",
69  verbose);
70  cmd.Parse(argc, argv);
71 
73  Ssid ssid;
74  std::string dataRate;
75  int freq;
76  Time dataStartTime =
77  MicroSeconds(800); // leaving enough time for beacon and association procedure
78  Time dataDuration =
79  MicroSeconds(300); // leaving enough time for data transfer (+ acknowledgment)
80  if (standard == "11a")
81  {
82  wifi.SetStandard(WIFI_STANDARD_80211a);
83  ssid = Ssid("ns380211a");
84  dataRate = "OfdmRate6Mbps";
85  freq = 5180;
86  if (bw != 20)
87  {
88  std::cout << "Bandwidth is not compatible with standard" << std::endl;
89  return 1;
90  }
91  }
92  else if (standard == "11p_10MHZ")
93  {
94  wifi.SetStandard(WIFI_STANDARD_80211p);
95  ssid = Ssid("ns380211p_10MHZ");
96  dataRate = "OfdmRate3MbpsBW10MHz";
97  freq = 5860;
98  dataStartTime = MicroSeconds(1400);
99  dataDuration = MicroSeconds(600);
100  if (bw != 10)
101  {
102  std::cout << "Bandwidth is not compatible with standard" << std::endl;
103  return 1;
104  }
105  }
106  else if (standard == "11p_5MHZ")
107  {
108  wifi.SetStandard(WIFI_STANDARD_80211p);
109  ssid = Ssid("ns380211p_5MHZ");
110  dataRate = "OfdmRate1_5MbpsBW5MHz";
111  freq = 5860;
112  dataStartTime = MicroSeconds(2500);
113  dataDuration = MicroSeconds(1200);
114  if (bw != 5)
115  {
116  std::cout << "Bandwidth is not compatible with standard" << std::endl;
117  return 1;
118  }
119  }
120  else if (standard == "11n_2_4GHZ")
121  {
122  wifi.SetStandard(WIFI_STANDARD_80211n);
123  ssid = Ssid("ns380211n_2_4GHZ");
124  dataRate = "HtMcs0";
125  freq = 2402 + (bw / 2); // so as to have 2412/2422 for 20/40
126  dataStartTime = MicroSeconds(4700);
127  dataDuration = MicroSeconds(400);
128  if (bw != 20 && bw != 40)
129  {
130  std::cout << "Bandwidth is not compatible with standard" << std::endl;
131  return 1;
132  }
133  }
134  else if (standard == "11n_5GHZ")
135  {
136  wifi.SetStandard(WIFI_STANDARD_80211n);
137  ssid = Ssid("ns380211n_5GHZ");
138  dataRate = "HtMcs0";
139  freq = 5170 + (bw / 2); // so as to have 5180/5190 for 20/40
140  dataStartTime = MicroSeconds(1000);
141  if (bw != 20 && bw != 40)
142  {
143  std::cout << "Bandwidth is not compatible with standard" << std::endl;
144  return 1;
145  }
146  }
147  else if (standard == "11ac")
148  {
149  wifi.SetStandard(WIFI_STANDARD_80211ac);
150  ssid = Ssid("ns380211ac");
151  dataRate = "VhtMcs0";
152  freq = 5170 + (bw / 2); // so as to have 5180/5190/5210/5250 for 20/40/80/160
153  dataStartTime = MicroSeconds(1100);
154  dataDuration += MicroSeconds(400); // account for ADDBA procedure
155  if (bw != 20 && bw != 40 && bw != 80 && bw != 160)
156  {
157  std::cout << "Bandwidth is not compatible with standard" << std::endl;
158  return 1;
159  }
160  }
161  else if (standard == "11ax_2_4GHZ")
162  {
163  wifi.SetStandard(WIFI_STANDARD_80211ax);
164  ssid = Ssid("ns380211ax_2_4GHZ");
165  dataRate = "HeMcs0";
166  freq = 2402 + (bw / 2); // so as to have 2412/2422/2442 for 20/40/80
167  dataStartTime = MicroSeconds(5500);
168  dataDuration += MicroSeconds(2000); // account for ADDBA procedure
169  if (bw != 20 && bw != 40 && bw != 80)
170  {
171  std::cout << "Bandwidth is not compatible with standard" << std::endl;
172  return 1;
173  }
174  }
175  else if (standard == "11ax_5GHZ")
176  {
177  wifi.SetStandard(WIFI_STANDARD_80211ax);
178  ssid = Ssid("ns380211ax_5GHZ");
179  dataRate = "HeMcs0";
180  freq = 5170 + (bw / 2); // so as to have 5180/5190/5210/5250 for 20/40/80/160
181  dataStartTime = MicroSeconds(1200);
182  dataDuration += MicroSeconds(500); // account for ADDBA procedure
183  if (bw != 20 && bw != 40 && bw != 80 && bw != 160)
184  {
185  std::cout << "Bandwidth is not compatible with standard" << std::endl;
186  return 1;
187  }
188  }
189  else
190  {
191  std::cout << "Unknown OFDM standard (please refer to the listed possible values)"
192  << std::endl;
193  return 1;
194  }
195 
196  if (verbose)
197  {
199  LogComponentEnable("WifiSpectrumValueHelper", LOG_LEVEL_ALL);
200  LogComponentEnable("SpectrumWifiPhy", LOG_LEVEL_ALL);
201  }
202 
203  /* nodes and positions */
204  NodeContainer wifiNodes;
205  NodeContainer spectrumAnalyzerNodes;
206  NodeContainer allNodes;
207  wifiNodes.Create(2);
208  spectrumAnalyzerNodes.Create(1);
209  allNodes.Add(wifiNodes);
210  allNodes.Add(spectrumAnalyzerNodes);
211  NodeContainer wifiStaNode;
213  wifiApNode.Add(wifiNodes.Get(0));
214  wifiStaNode.Add(wifiNodes.Get(1));
215 
216  /* channel and propagation */
218  channelHelper.SetChannel("ns3::MultiModelSpectrumChannel");
219  // constant path loss added just to show capability to set different propagation loss models
220  // FriisSpectrumPropagationLossModel already added by default in SpectrumChannelHelper
221  channelHelper.AddSpectrumPropagationLoss("ns3::ConstantSpectrumPropagationLossModel");
222  Ptr<SpectrumChannel> channel = channelHelper.Create();
223 
224  /* Wi-Fi transmitter setup */
225 
226  SpectrumWifiPhyHelper spectrumPhy;
227  spectrumPhy.SetChannel(channel);
228  spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
229  spectrumPhy.Set("Frequency", UintegerValue(freq));
230  spectrumPhy.Set("ChannelWidth", UintegerValue(bw));
231  spectrumPhy.Set("TxPowerStart", DoubleValue(pow)); // dBm
232  spectrumPhy.Set("TxPowerEnd", DoubleValue(pow));
233 
235  wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
236  "DataMode",
237  StringValue(dataRate),
238  "ControlMode",
239  StringValue(dataRate));
240 
241  mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid), "ActiveProbing", BooleanValue(false));
242  NetDeviceContainer staDevice = wifi.Install(spectrumPhy, mac, wifiStaNode);
243  mac.SetType("ns3::ApWifiMac",
244  "Ssid",
245  SsidValue(ssid),
246  "EnableBeaconJitter",
247  BooleanValue(false)); // so as to be sure that first beacon arrives quickly
248  NetDeviceContainer apDevice = wifi.Install(spectrumPhy, mac, wifiApNode);
249 
251  Ptr<ListPositionAllocator> nodePositionList = CreateObject<ListPositionAllocator>();
252  nodePositionList->Add(Vector(0.0, 1.0, 0.0)); // AP
253  nodePositionList->Add(Vector(1.0, 0.0, 0.0)); // STA
254  nodePositionList->Add(Vector(0.0, 0.0, 0.0)); // Spectrum Analyzer
255  mobility.SetPositionAllocator(nodePositionList);
256  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
257  mobility.Install(allNodes);
258 
259  /* Need to send data packet because beacon and association frames shall be sent using lowest
260  * rate */
261  // Send one data packet (this packet is sent using data rate / MCS defined above) once
262  // association is done (otherwise dropped)
263  Simulator::Schedule(dataStartTime,
264  &SendPacket,
265  apDevice.Get(0),
266  staDevice.Get(0)->GetAddress());
267 
268  /* frequency range for spectrum analyzer */
269  std::vector<double> freqs;
270  int margin = 2; // 1MHz margin on each side
271  int band = (bw + margin);
272  freqs.reserve(4 * 10 * band);
273  for (int i = 0; i < (4 * 10 * band); ++i) // conversion to 100kHz scale
274  {
275  freqs.push_back(i * 1e5 + (freq - 2 * band) * 1e6);
276  }
277  Ptr<SpectrumModel> spectrumAnalyzerFreqModel = Create<SpectrumModel>(freqs);
278 
279  /* spectrum analyzer setup */
280  SpectrumAnalyzerHelper spectrumAnalyzerHelper;
281  spectrumAnalyzerHelper.SetChannel(channel);
282  spectrumAnalyzerHelper.SetRxSpectrumModel(spectrumAnalyzerFreqModel);
283  spectrumAnalyzerHelper.SetPhyAttribute(
284  "Resolution",
285  TimeValue(MicroSeconds(4))); // enough resolution to distinguish OFDM symbols (default 1ms
286  // too long even for PPDUs)
287  std::ostringstream ossFileName;
288  ossFileName << "spectrum-analyzer-wifi-" << standard << "-" << bw << "MHz";
289  spectrumAnalyzerHelper.EnableAsciiAll(ossFileName.str());
290  NetDeviceContainer spectrumAnalyzerDevices =
291  spectrumAnalyzerHelper.Install(spectrumAnalyzerNodes);
292 
293  /* Let enough time for first beacon, association procedure, and first data (+acknowledgment and
294  * eventually preceding ADDBA procedure) */
295  Simulator::Stop(dataStartTime + dataDuration);
296 
297  Simulator::Run();
298 
299  /* Plot transmitted spectra with Gnuplot */
300  ossFileName << "-2-0"; // append node-interface info
301  std::ostringstream ossPlt;
302  ossPlt << ossFileName.str() << ".plt";
303  std::ofstream plotFile(ossPlt.str());
304  std::ostringstream ossPng;
305  ossPng << ossFileName.str() << ".png";
306  Gnuplot plot = Gnuplot(ossPng.str());
307  // Prepare 3D plot (reset previous values)
308  std::ostringstream ossExtra;
309  ossExtra << "file = '" << ossFileName.str() << "'";
310  plot.SetExtra(ossExtra.str());
311  plot.AppendExtra("unset surface");
312  plot.AppendExtra("set key off");
313  // Configure output file as png
314  plot.AppendExtra("set term png");
315  plot.AppendExtra("set output file . '.png'");
316  // Switch to 3D plot
317  plot.AppendExtra("set pm3d at s");
318  plot.AppendExtra("set palette");
319  // Orient view
320  plot.AppendExtra("set view 50,50");
321  // Add legends
322  plot.AppendExtra("set xlabel \"time (ms)\"");
323  plot.AppendExtra("set ylabel \"freq (MHz)\" offset 15,0,0");
324  plot.AppendExtra("set zlabel \"PSD (dBW/Hz)\" offset 15,0,0");
325  // Define grid
326  plot.AppendExtra("set ytics");
327  plot.AppendExtra("set mytics 2");
328  plot.AppendExtra("set ztics");
329  plot.AppendExtra("set mztics 5");
330  plot.AppendExtra("set grid ytics mytics ztics mztics");
331  // tr file name
332  plot.AppendExtra("filename = file . '.tr'");
333  // Extract max power using stats (so as to normalize during display)
334  plot.AppendExtra("stats filename using 3");
335  plot.AppendExtra("refW = STATS_max");
336  // Plot graph (file being defined upon gnuplot call)
337  plot.AppendExtra("splot filename using ($1*1000.0):($2/1e6):(10*log10($3/refW))");
338  // Generate output and close file
339  plot.GenerateOutput(plotFile);
340  plotFile.close();
341 
343 
344  std::cout << "Simulation done!" << std::endl;
345  std::cout << "See spectrum analyzer output file: " << ossFileName.str() << ".tr" << std::endl;
346  std::cout << "To generate plot simply execute the following command: gnuplot "
347  << ossFileName.str() << ".plt" << std::endl;
348 
349  return 0;
350 }
a polymophic address class
Definition: address.h:101
Parse command-line arguments.
Definition: command-line.h:232
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
a simple class to generate gnuplot-ready plotting commands from a set of datasets.
Definition: gnuplot.h:373
void AppendExtra(const std::string &extra)
Definition: gnuplot.cc:752
void GenerateOutput(std::ostream &os)
Writes gnuplot commands and data values to a single output stream.
Definition: gnuplot.cc:765
void SetExtra(const std::string &extra)
Definition: gnuplot.cc:746
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
void Add(const NodeContainer &nc)
Append the contents of another NodeContainer to the end of this container.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
Class to allow the Spectrum Analysis.
NetDeviceContainer Install(NodeContainer c) const
void SetPhyAttribute(std::string name, const AttributeValue &v)
void SetChannel(Ptr< SpectrumChannel > channel)
Set the SpectrumChannel that will be used by SpectrumPhy instances created by this helper.
void EnableAsciiAll(std::string prefix)
Enable ASCII output.
void SetRxSpectrumModel(Ptr< SpectrumModel > m)
Set the spectrum model used by the created SpectrumAnalyzer instances to represent incoming signals.
Setup a SpectrumChannel.
Ptr< SpectrumChannel > Create() const
static SpectrumChannelHelper Default()
Setup a default SpectrumChannel.
void AddSpectrumPropagationLoss(std::string name, Ts &&... args)
void SetChannel(std::string type, Ts &&... args)
Make it easy to create and manage PHY objects for the spectrum model.
void SetChannel(const Ptr< SpectrumChannel > channel)
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
create MAC layers for a ns3::WifiNetDevice.
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:163
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
Definition: wifi-helper.h:550
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211p
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:302
@ LOG_LEVEL_ALL
Print everything.
Definition: log.h:116
@ LOG_PREFIX_ALL
All prefixes.
Definition: log.h:122
void LogComponentEnableAll(LogLevel level)
Enable the logging output for all registered log components.
Definition: log.cc:320
cmd
Definition: second.py:40
ssid
Definition: third.py:93
channel
Definition: third.py:88
mac
Definition: third.py:92
wifi
Definition: third.py:95
wifiApNode
Definition: third.py:86
mobility
Definition: third.py:105
bool verbose
void SendPacket(Ptr< NetDevice > sourceDevice, Address &destination)
This example (inspired from tv-trans-example) enables to generate the transmitted spectra of Wi-Fi st...