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 * 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
30using namespace ns3;
31
46void
47SendPacket(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
53int
54main(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
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
AttributeValue implementation for Boolean.
Definition: boolean.h:37
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:370
void AppendExtra(const std::string &extra)
Definition: gnuplot.cc:789
void GenerateOutput(std::ostream &os)
Writes gnuplot commands and data values to a single output stream.
Definition: gnuplot.cc:802
void SetExtra(const std::string &extra)
Definition: gnuplot.cc:783
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
AttributeValue implementation for Ssid.
Definition: ssid.h:96
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1413
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
ns cmd
Definition: second.py:40
ns wifi
Definition: third.py:95
ns ssid
Definition: third.py:93
ns mac
Definition: third.py:92
ns wifiApNode
Definition: third.py:86
ns channel
Definition: third.py:88
ns 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...