A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-trans-example.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 Orange Labs
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Rediet <getachew.redieteab@orange.com>
7 */
8
9#include "ns3/command-line.h"
10#include "ns3/gnuplot.h"
11#include "ns3/mobility-helper.h"
12#include "ns3/spectrum-analyzer-helper.h"
13#include "ns3/spectrum-channel.h"
14#include "ns3/spectrum-helper.h"
15#include "ns3/spectrum-wifi-helper.h"
16#include "ns3/ssid.h"
17#include "ns3/string.h"
18#include "ns3/wifi-utils.h"
19
20using namespace ns3;
21
22/**
23 * This example (inspired from tv-trans-example) enables to generate the transmitted spectra of
24 * Wi-Fi stations, so as to model transmit mask imperfections of OFDM-based Wi-Fi standards.
25 * Only one data packet is sent from access point to station (once association has been performed)
26 * so as to reduce execution time.
27 *
28 * A spectrum analyzer is used to measure the transmitted spectra from Wi-Fi stations.
29 * The file "spectrum-analyzer-wifi-[standard]-[bandwidth]MHz-sim-2-0.tr" contains its
30 * output post simulation and use it to plot transmitted spectra with Gnuplot.
31 *
32 * The wifi-trans-example.sh script runs this example for all combinations, plots transmitted
33 * spectra, and puts resulting png images in wifi-trans-results folder.
34 */
35
36void
37SendPacket(Ptr<NetDevice> sourceDevice, Address& destination)
38{
39 Ptr<Packet> pkt = Create<Packet>(100); // dummy bytes of data
40 sourceDevice->Send(pkt, destination, 0);
41}
42
43int
44main(int argc, char** argv)
45{
46 std::string standardStr = "11a";
47 MHz_u bw{20};
48 dBm_u pow{23};
49 bool verbose = false;
50 CommandLine cmd(__FILE__);
51 cmd.AddValue("standard",
52 "OFDM-based Wi-Fi standard [11a, 11p_10MHZ, 11p_5MHZ, 11n_2_4GHZ, 11n_5GHZ, 11ac, "
53 "11ax_2_4GHZ, 11ax_5GHZ]",
54 standardStr);
55 cmd.AddValue("bw", "Bandwidth (consistent with standard, in MHz)", bw);
56 cmd.AddValue("txPower", "Transmit power (dBm)", pow);
57 cmd.AddValue("verbose",
58 "Display log messages for WifiSpectrumValueHelper and SpectrumWifiPhy",
59 verbose);
60 cmd.Parse(argc, argv);
61
63 Ssid ssid;
64 std::string dataRate;
65 MHz_u freq;
66 Time dataStartTime =
67 MicroSeconds(800); // leaving enough time for beacon and association procedure
68 Time dataDuration =
69 MicroSeconds(300); // leaving enough time for data transfer (+ acknowledgment)
70 WifiStandard standard{WifiStandard::WIFI_STANDARD_UNSPECIFIED};
72 std::string channelBand;
73 if (standardStr == "11a")
74 {
75 standard = WIFI_STANDARD_80211a;
76 phyBand = WIFI_PHY_BAND_5GHZ;
77 channelBand = "BAND_5GHZ";
78 ssid = Ssid("ns380211a");
79 dataRate = "OfdmRate6Mbps";
80 freq = MHz_u{5180};
81 if (bw != MHz_u{20})
82 {
83 std::cout << "Bandwidth is not compatible with standard" << std::endl;
84 return 1;
85 }
86 }
87 else if (standardStr == "11p_10MHZ")
88 {
89 standard = WIFI_STANDARD_80211p;
90 phyBand = WIFI_PHY_BAND_5GHZ;
91 channelBand = "BAND_5GHZ";
92 ssid = Ssid("ns380211p_10MHZ");
93 dataRate = "OfdmRate3MbpsBW10MHz";
94 freq = MHz_u{5860};
95 dataStartTime = MicroSeconds(1400);
96 dataDuration = MicroSeconds(600);
97 if (bw != MHz_u{10})
98 {
99 std::cout << "Bandwidth is not compatible with standard" << std::endl;
100 return 1;
101 }
102 }
103 else if (standardStr == "11p_5MHZ")
104 {
105 standard = WIFI_STANDARD_80211p;
106 phyBand = WIFI_PHY_BAND_5GHZ;
107 channelBand = "BAND_5GHZ";
108 ssid = Ssid("ns380211p_5MHZ");
109 dataRate = "OfdmRate1_5MbpsBW5MHz";
110 freq = MHz_u{5860};
111 dataStartTime = MicroSeconds(2500);
112 dataDuration = MicroSeconds(1200);
113 if (bw != MHz_u{5})
114 {
115 std::cout << "Bandwidth is not compatible with standard" << std::endl;
116 return 1;
117 }
118 }
119 else if (standardStr == "11n_2_4GHZ")
120 {
121 standard = WIFI_STANDARD_80211n;
122 phyBand = WIFI_PHY_BAND_2_4GHZ;
123 channelBand = "BAND_2_4GHZ";
124 ssid = Ssid("ns380211n_2_4GHZ");
125 dataRate = "HtMcs0";
126 freq = MHz_u{2402} + (bw / 2); // so as to have 2412/2422 for 20/40
127 dataStartTime = MicroSeconds(4700);
128 dataDuration = MicroSeconds(400);
129 if (bw != MHz_u{20} && bw != MHz_u{40})
130 {
131 std::cout << "Bandwidth is not compatible with standard" << std::endl;
132 return 1;
133 }
134 }
135 else if (standardStr == "11n_5GHZ")
136 {
137 standard = WIFI_STANDARD_80211n;
138 phyBand = WIFI_PHY_BAND_5GHZ;
139 channelBand = "BAND_5GHZ";
140 ssid = Ssid("ns380211n_5GHZ");
141 dataRate = "HtMcs0";
142 freq = MHz_u{5170} + (bw / 2); // so as to have 5180/5190 for 20/40
143 dataStartTime = MicroSeconds(1000);
144 if (bw != MHz_u{20} && bw != MHz_u{40})
145 {
146 std::cout << "Bandwidth is not compatible with standard" << std::endl;
147 return 1;
148 }
149 }
150 else if (standardStr == "11ac")
151 {
152 standard = WIFI_STANDARD_80211ac;
153 phyBand = WIFI_PHY_BAND_5GHZ;
154 channelBand = "BAND_5GHZ";
155 ssid = Ssid("ns380211ac");
156 dataRate = "VhtMcs0";
157 freq = MHz_u{5170} + (bw / 2); // so as to have 5180/5190/5210/5250 for 20/40/80/160
158 dataStartTime = MicroSeconds(1100);
159 dataDuration += MicroSeconds(400); // account for ADDBA procedure
160 if (bw != MHz_u{20} && bw != MHz_u{40} && bw != MHz_u{80} && bw != MHz_u{160})
161 {
162 std::cout << "Bandwidth is not compatible with standard" << std::endl;
163 return 1;
164 }
165 }
166 else if (standardStr == "11ax_2_4GHZ")
167 {
168 standard = WIFI_STANDARD_80211ax;
169 phyBand = WIFI_PHY_BAND_2_4GHZ;
170 channelBand = "BAND_2_4GHZ";
171 ssid = Ssid("ns380211ax_2_4GHZ");
172 dataRate = "HeMcs0";
173 freq = MHz_u{2402} + (bw / 2); // so as to have 2412/2422/2442 for 20/40/80
174 dataStartTime = MicroSeconds(5500);
175 dataDuration += MicroSeconds(2000); // account for ADDBA procedure
176 if (bw != MHz_u{20} && bw != MHz_u{40} && bw != MHz_u{80})
177 {
178 std::cout << "Bandwidth is not compatible with standard" << std::endl;
179 return 1;
180 }
181 }
182 else if (standardStr == "11ax_5GHZ")
183 {
184 standard = WIFI_STANDARD_80211ax;
185 phyBand = WIFI_PHY_BAND_5GHZ;
186 channelBand = "BAND_5GHZ";
187 ssid = Ssid("ns380211ax_5GHZ");
188 dataRate = "HeMcs0";
189 freq = MHz_u{5170} + (bw / 2); // so as to have 5180/5190/5210/5250 for 20/40/80/160
190 dataStartTime = MicroSeconds(1200);
191 dataDuration += MicroSeconds(500); // account for ADDBA procedure
192 if (bw != MHz_u{20} && bw != MHz_u{40} && bw != MHz_u{80} && bw != MHz_u{160})
193 {
194 std::cout << "Bandwidth is not compatible with standard" << std::endl;
195 return 1;
196 }
197 }
198 else
199 {
200 std::cout << "Unknown OFDM standard (please refer to the listed possible values)"
201 << std::endl;
202 return 1;
203 }
204
205 if (verbose)
206 {
208 LogComponentEnable("WifiSpectrumValueHelper", LOG_LEVEL_ALL);
209 LogComponentEnable("SpectrumWifiPhy", LOG_LEVEL_ALL);
210 }
211
212 /* nodes and positions */
213 NodeContainer wifiNodes;
214 NodeContainer spectrumAnalyzerNodes;
215 NodeContainer allNodes;
216 wifiNodes.Create(2);
217 spectrumAnalyzerNodes.Create(1);
218 allNodes.Add(wifiNodes);
219 allNodes.Add(spectrumAnalyzerNodes);
220 NodeContainer wifiStaNode;
222 wifiApNode.Add(wifiNodes.Get(0));
223 wifiStaNode.Add(wifiNodes.Get(1));
224
225 /* channel and propagation */
227 channelHelper.SetChannel("ns3::MultiModelSpectrumChannel");
228 // constant path loss added just to show capability to set different propagation loss models
229 // FriisSpectrumPropagationLossModel already added by default in SpectrumChannelHelper
230 channelHelper.AddSpectrumPropagationLoss("ns3::ConstantSpectrumPropagationLossModel");
231 Ptr<SpectrumChannel> channel = channelHelper.Create();
232
233 /* Wi-Fi transmitter setup */
234
235 SpectrumWifiPhyHelper spectrumPhy;
236 spectrumPhy.SetChannel(channel);
237 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
238 spectrumPhy.Set("TxPowerStart", DoubleValue(pow)); // dBm
239 spectrumPhy.Set("TxPowerEnd", DoubleValue(pow));
240 auto channelNumber = WifiPhyOperatingChannel::FindFirst(0, freq, bw, standard, phyBand)->number;
241 std::ostringstream channelSettings;
242 channelSettings << "{" << +channelNumber << ", " << bw << ", " << channelBand << ", 0}";
243 spectrumPhy.Set("ChannelSettings", StringValue(channelSettings.str()));
244
246 wifi.SetStandard(standard);
247 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
248 "DataMode",
249 StringValue(dataRate),
250 "ControlMode",
251 StringValue(dataRate));
252
253 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid), "ActiveProbing", BooleanValue(false));
254 NetDeviceContainer staDevice = wifi.Install(spectrumPhy, mac, wifiStaNode);
255 mac.SetType("ns3::ApWifiMac",
256 "Ssid",
257 SsidValue(ssid),
258 "EnableBeaconJitter",
259 BooleanValue(false)); // so as to be sure that first beacon arrives quickly
260 NetDeviceContainer apDevice = wifi.Install(spectrumPhy, mac, wifiApNode);
261
264 nodePositionList->Add(Vector(0.0, 1.0, 0.0)); // AP
265 nodePositionList->Add(Vector(1.0, 0.0, 0.0)); // STA
266 nodePositionList->Add(Vector(0.0, 0.0, 0.0)); // Spectrum Analyzer
267 mobility.SetPositionAllocator(nodePositionList);
268 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
269 mobility.Install(allNodes);
270
271 /* Need to send data packet because beacon and association frames shall be sent using lowest
272 * rate */
273 // Send one data packet (this packet is sent using data rate / MCS defined above) once
274 // association is done (otherwise dropped)
275 Simulator::Schedule(dataStartTime,
276 &SendPacket,
277 apDevice.Get(0),
278 staDevice.Get(0)->GetAddress());
279
280 /* frequency range for spectrum analyzer */
281 std::vector<double> freqs;
282 const MHz_u margin{2}; // 1MHz margin on each side
283 const auto band = (bw + margin);
284 freqs.reserve(4 * 10 * band);
285 const MHz_u scale{0.1};
286 for (int i = 0; i < (4 * 10 * band); ++i) // conversion to 100kHz scale
287 {
288 freqs.push_back(MHzToHz((i * scale) + (freq - 2 * band)));
289 }
290 Ptr<SpectrumModel> spectrumAnalyzerFreqModel = Create<SpectrumModel>(freqs);
291
292 /* spectrum analyzer setup */
293 SpectrumAnalyzerHelper spectrumAnalyzerHelper;
294 spectrumAnalyzerHelper.SetChannel(channel);
295 spectrumAnalyzerHelper.SetRxSpectrumModel(spectrumAnalyzerFreqModel);
296 spectrumAnalyzerHelper.SetPhyAttribute(
297 "Resolution",
298 TimeValue(MicroSeconds(4))); // enough resolution to distinguish OFDM symbols (default 1ms
299 // too long even for PPDUs)
300 std::ostringstream ossFileName;
301 ossFileName << "spectrum-analyzer-wifi-" << standardStr << "-" << bw << "MHz";
302 spectrumAnalyzerHelper.EnableAsciiAll(ossFileName.str());
303 NetDeviceContainer spectrumAnalyzerDevices =
304 spectrumAnalyzerHelper.Install(spectrumAnalyzerNodes);
305
306 /* Let enough time for first beacon, association procedure, and first data (+acknowledgment and
307 * eventually preceding ADDBA procedure) */
308 Simulator::Stop(dataStartTime + dataDuration);
309
311
312 /* Plot transmitted spectra with Gnuplot */
313 ossFileName << "-2-0"; // append node-interface info
314 std::ostringstream ossPlt;
315 ossPlt << ossFileName.str() << ".plt";
316 std::ofstream plotFile(ossPlt.str());
317 std::ostringstream ossPng;
318 ossPng << ossFileName.str() << ".png";
319 Gnuplot plot = Gnuplot(ossPng.str());
320 // Prepare 3D plot (reset previous values)
321 std::ostringstream ossExtra;
322 ossExtra << "file = '" << ossFileName.str() << "'";
323 plot.SetExtra(ossExtra.str());
324 plot.AppendExtra("unset surface");
325 plot.AppendExtra("set key off");
326 // Configure output file as png
327 plot.AppendExtra("set term png");
328 plot.AppendExtra("set output file . '.png'");
329 // Switch to 3D plot
330 plot.AppendExtra("set pm3d at s");
331 plot.AppendExtra("set palette");
332 // Orient view
333 plot.AppendExtra("set view 50,50");
334 // Add legends
335 plot.AppendExtra("set xlabel \"time (ms)\"");
336 plot.AppendExtra("set ylabel \"freq (MHz)\" offset 15,0,0");
337 plot.AppendExtra("set zlabel \"PSD (dBW/Hz)\" offset 15,0,0");
338 // Define grid
339 plot.AppendExtra("set ytics");
340 plot.AppendExtra("set mytics 2");
341 plot.AppendExtra("set ztics");
342 plot.AppendExtra("set mztics 5");
343 plot.AppendExtra("set grid ytics mytics ztics mztics");
344 // tr file name
345 plot.AppendExtra("filename = file . '.tr'");
346 // Extract max power using stats (so as to normalize during display)
347 plot.AppendExtra("stats filename using 3");
348 plot.AppendExtra("refW = STATS_max");
349 // Plot graph (file being defined upon gnuplot call)
350 plot.AppendExtra("splot filename using ($1*1000.0):($2/1e6):(10*log10($3/refW))");
351 // Generate output and close file
352 plot.GenerateOutput(plotFile);
353 plotFile.close();
354
356
357 std::cout << "Simulation done!" << std::endl;
358 std::cout << "See spectrum analyzer output file: " << ossFileName.str() << ".tr" << std::endl;
359 std::cout << "To generate plot simply execute the following command: gnuplot "
360 << ossFileName.str() << ".plt" << std::endl;
361
362 return 0;
363}
a polymophic address class
Definition address.h:90
AttributeValue implementation for Boolean.
Definition boolean.h:26
Parse command-line arguments.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
a simple class to generate gnuplot-ready plotting commands from a set of datasets.
Definition gnuplot.h:359
void AppendExtra(const std::string &extra)
Definition gnuplot.cc:778
void GenerateOutput(std::ostream &os)
Writes gnuplot commands and data values to a single output stream.
Definition gnuplot.cc:791
void SetExtra(const std::string &extra)
Definition gnuplot.cc:772
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.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
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:25
AttributeValue implementation for Ssid.
Definition ssid.h:85
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
AttributeValue implementation for Time.
Definition nstime.h:1431
helps to create WifiNetDevice objects
create MAC layers for a ns3::WifiNetDevice.
void Set(std::string name, const AttributeValue &v)
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
static ConstIterator FindFirst(uint8_t number, MHz_u frequency, MHz_u width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first frequency segment matching the specified parameters.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1368
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiPhyBand
Identifies the PHY band.
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211p
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
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:291
@ LOG_LEVEL_ALL
Print everything.
Definition log.h:105
@ LOG_PREFIX_ALL
All prefixes.
Definition log.h:111
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
Definition wifi-utils.h:109
void LogComponentEnableAll(LogLevel level)
Enable the logging output for all registered log components.
Definition log.cc:309
ssid
Definition third.py:82
channel
Definition third.py:77
mac
Definition third.py:81
wifi
Definition third.py:84
wifiApNode
Definition third.py:75
mobility
Definition third.py:92
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...