A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-80211n-mimo.cc
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: GPL-2.0-only
3 *
4 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
5 */
6
7// This example is used to validate 802.11n MIMO.
8//
9// It outputs plots of the throughput versus the distance
10// for every HT MCS value and from 1 to 4 MIMO streams.
11//
12// The simulation assumes a single station in an infrastructure network:
13//
14// STA AP
15// * *
16// | |
17// n1 n2
18//
19// The user can choose whether UDP or TCP should be used and can configure
20// some 802.11n parameters (frequency, channel width and guard interval).
21//
22// An important configuration parameter is preamble detection. It is enabled
23// by default (to match the default ns-3 configuration) but will dominate
24// performance at low SNRs, causing the different MCS to appear to have
25// the same range (because regardless of the MCS, the preamble detection
26// thresholds do not change).
27
28#include "ns3/boolean.h"
29#include "ns3/command-line.h"
30#include "ns3/config.h"
31#include "ns3/double.h"
32#include "ns3/gnuplot.h"
33#include "ns3/ht-phy.h"
34#include "ns3/internet-stack-helper.h"
35#include "ns3/ipv4-address-helper.h"
36#include "ns3/ipv4-global-routing-helper.h"
37#include "ns3/mobility-helper.h"
38#include "ns3/on-off-helper.h"
39#include "ns3/packet-sink-helper.h"
40#include "ns3/packet-sink.h"
41#include "ns3/ssid.h"
42#include "ns3/string.h"
43#include "ns3/udp-client-server-helper.h"
44#include "ns3/udp-server.h"
45#include "ns3/uinteger.h"
46#include "ns3/yans-wifi-channel.h"
47#include "ns3/yans-wifi-helper.h"
48
49using namespace ns3;
50
51int
52main(int argc, char* argv[])
53{
54 std::ofstream file("80211n-mimo-throughput.plt");
55
56 std::vector<std::string> modes = {
57 "HtMcs0", "HtMcs1", "HtMcs2", "HtMcs3", "HtMcs4", "HtMcs5", "HtMcs6", "HtMcs7",
58 "HtMcs8", "HtMcs9", "HtMcs10", "HtMcs11", "HtMcs12", "HtMcs13", "HtMcs14", "HtMcs15",
59 "HtMcs16", "HtMcs17", "HtMcs18", "HtMcs19", "HtMcs20", "HtMcs21", "HtMcs22", "HtMcs23",
60 "HtMcs24", "HtMcs25", "HtMcs26", "HtMcs27", "HtMcs28", "HtMcs29", "HtMcs30", "HtMcs31",
61 };
62
63 bool udp{true};
64 Time simulationTime{"5s"};
65 double frequency{5.0}; // whether 2.4 or 5.0 GHz
66 double step{5}; // meters
67 bool shortGuardInterval{false};
68 bool channelBonding{false};
69 bool preambleDetection{true};
70
71 CommandLine cmd(__FILE__);
72 cmd.AddValue("step", "Granularity of the results to be plotted in meters", step);
73 cmd.AddValue("simulationTime", "Simulation time per step", simulationTime);
74 cmd.AddValue("channelBonding",
75 "Enable/disable channel bonding (channel width = 20 MHz if false, channel width = "
76 "40 MHz if true)",
77 channelBonding);
78 cmd.AddValue("preambleDetection", "Enable/disable preamble detection model", preambleDetection);
79 cmd.AddValue("shortGuardInterval", "Enable/disable short guard interval", shortGuardInterval);
80 cmd.AddValue("frequency",
81 "Whether working in the 2.4 or 5.0 GHz band (other values gets rejected)",
82 frequency);
83 cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp);
84 cmd.Parse(argc, argv);
85
86 Gnuplot plot = Gnuplot("80211n-mimo-throughput.eps");
87
88 for (uint32_t i = 0; i < modes.size(); i++) // MCS
89 {
90 std::cout << modes[i] << std::endl;
91 Gnuplot2dDataset dataset(modes[i]);
92 for (double d = 0; d <= 100;) // distance
93 {
94 std::cout << "Distance = " << d << "m: " << std::endl;
95 uint32_t payloadSize; // 1500 byte IP packet
96 if (udp)
97 {
98 payloadSize = 1472; // bytes
99 }
100 else
101 {
102 payloadSize = 1448; // bytes
103 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(payloadSize));
104 }
105
106 uint8_t nStreams = 1 + (i / 8); // number of MIMO streams
107
108 NodeContainer wifiStaNode;
109 wifiStaNode.Create(1);
111 wifiApNode.Create(1);
112
115 phy.SetChannel(channel.Create());
116 if (!preambleDetection)
117 {
118 phy.DisablePreambleDetectionModel();
119 }
120
121 // Set MIMO capabilities
122 phy.Set("Antennas", UintegerValue(nStreams));
123 phy.Set("MaxSupportedTxSpatialStreams", UintegerValue(nStreams));
124 phy.Set("MaxSupportedRxSpatialStreams", UintegerValue(nStreams));
125 phy.Set("ChannelSettings",
126 StringValue(std::string("{0, ") + (channelBonding ? "40, " : "20, ") +
127 (frequency == 2.4 ? "BAND_2_4GHZ" : "BAND_5GHZ") + ", 0}"));
128
131 if (frequency == 5.0)
132 {
133 wifi.SetStandard(WIFI_STANDARD_80211n);
134 }
135 else if (frequency == 2.4)
136 {
137 wifi.SetStandard(WIFI_STANDARD_80211n);
138 Config::SetDefault("ns3::LogDistancePropagationLossModel::ReferenceLoss",
139 DoubleValue(40.046));
140 }
141 else
142 {
143 std::cout << "Wrong frequency value!" << std::endl;
144 return 0;
145 }
146
147 StringValue ctrlRate;
148 if (frequency == 2.4)
149 {
150 ctrlRate = StringValue("ErpOfdmRate24Mbps");
151 }
152 else
153 {
154 ctrlRate = StringValue("OfdmRate24Mbps");
155 }
156 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
157 "DataMode",
158 StringValue(modes[i]),
159 "ControlMode",
160 ctrlRate);
161
162 Ssid ssid = Ssid("ns3-80211n");
163
164 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
165
166 NetDeviceContainer staDevice;
167 staDevice = wifi.Install(phy, mac, wifiStaNode);
168
169 mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
170
171 NetDeviceContainer apDevice;
172 apDevice = wifi.Install(phy, mac, wifiApNode);
173
174 // Set guard interval
175 Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/"
176 "ShortGuardIntervalSupported",
177 BooleanValue(shortGuardInterval));
178
179 // mobility.
182
183 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
184 positionAlloc->Add(Vector(d, 0.0, 0.0));
185 mobility.SetPositionAllocator(positionAlloc);
186
187 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
188
189 mobility.Install(wifiApNode);
190 mobility.Install(wifiStaNode);
191
192 /* Internet stack*/
194 stack.Install(wifiApNode);
195 stack.Install(wifiStaNode);
196
198 address.SetBase("192.168.1.0", "255.255.255.0");
199 Ipv4InterfaceContainer staNodeInterface;
200 Ipv4InterfaceContainer apNodeInterface;
201
202 staNodeInterface = address.Assign(staDevice);
203 apNodeInterface = address.Assign(apDevice);
204
205 /* Setting applications */
206 const auto maxLoad = HtPhy::GetDataRate(i,
207 channelBonding ? 40 : 20,
208 NanoSeconds(shortGuardInterval ? 400 : 800),
209 nStreams);
210 ApplicationContainer serverApp;
211 if (udp)
212 {
213 // UDP flow
214 uint16_t port = 9;
216 serverApp = server.Install(wifiStaNode.Get(0));
217 serverApp.Start(Seconds(0.0));
218 serverApp.Stop(simulationTime + Seconds(1.0));
219 const auto packetInterval = payloadSize * 8.0 / maxLoad;
220
221 UdpClientHelper client(staNodeInterface.GetAddress(0), port);
222 client.SetAttribute("MaxPackets", UintegerValue(4294967295U));
223 client.SetAttribute("Interval", TimeValue(Seconds(packetInterval)));
224 client.SetAttribute("PacketSize", UintegerValue(payloadSize));
225 ApplicationContainer clientApp = client.Install(wifiApNode.Get(0));
226 clientApp.Start(Seconds(1.0));
227 clientApp.Stop(simulationTime + Seconds(1.0));
228 }
229 else
230 {
231 // TCP flow
232 uint16_t port = 50000;
234 PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress);
235 serverApp = packetSinkHelper.Install(wifiStaNode.Get(0));
236 serverApp.Start(Seconds(0.0));
237 serverApp.Stop(simulationTime + Seconds(1.0));
238
239 OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny());
240 onoff.SetAttribute("OnTime",
241 StringValue("ns3::ConstantRandomVariable[Constant=1]"));
242 onoff.SetAttribute("OffTime",
243 StringValue("ns3::ConstantRandomVariable[Constant=0]"));
244 onoff.SetAttribute("PacketSize", UintegerValue(payloadSize));
245 onoff.SetAttribute("DataRate", DataRateValue(maxLoad));
247 onoff.SetAttribute("Remote", remoteAddress);
248 ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0));
249 clientApp.Start(Seconds(1.0));
250 clientApp.Stop(simulationTime + Seconds(1.0));
251 }
252
254
255 Simulator::Stop(simulationTime + Seconds(1.0));
257
258 double throughput = 0;
259 if (udp)
260 {
261 // UDP
262 double totalPacketsThrough =
263 DynamicCast<UdpServer>(serverApp.Get(0))->GetReceived();
264 throughput = totalPacketsThrough * payloadSize * 8 /
265 simulationTime.GetMicroSeconds(); // Mbit/s
266 }
267 else
268 {
269 // TCP
270 double totalPacketsThrough =
271 DynamicCast<PacketSink>(serverApp.Get(0))->GetTotalRx();
272 throughput = totalPacketsThrough * 8 / simulationTime.GetMicroSeconds(); // Mbit/s
273 }
274 dataset.Add(d, throughput);
275 std::cout << throughput << " Mbit/s" << std::endl;
276 d += step;
278 }
279 plot.AddDataset(dataset);
280 }
281
282 plot.SetTerminal("postscript eps color enh \"Times-BoldItalic\"");
283 plot.SetLegend("Distance (Meters)", "Throughput (Mbit/s)");
284 plot.SetExtra("set xrange [0:100]\n\
285set yrange [0:600]\n\
286set ytics 0,50,600\n\
287set style line 1 dashtype 1 linewidth 5\n\
288set style line 2 dashtype 1 linewidth 5\n\
289set style line 3 dashtype 1 linewidth 5\n\
290set style line 4 dashtype 1 linewidth 5\n\
291set style line 5 dashtype 1 linewidth 5\n\
292set style line 6 dashtype 1 linewidth 5\n\
293set style line 7 dashtype 1 linewidth 5\n\
294set style line 8 dashtype 1 linewidth 5\n\
295set style line 9 dashtype 2 linewidth 5\n\
296set style line 10 dashtype 2 linewidth 5\n\
297set style line 11 dashtype 2 linewidth 5\n\
298set style line 12 dashtype 2 linewidth 5\n\
299set style line 13 dashtype 2 linewidth 5\n\
300set style line 14 dashtype 2 linewidth 5\n\
301set style line 15 dashtype 2 linewidth 5\n\
302set style line 16 dashtype 2 linewidth 5\n\
303set style line 17 dashtype 3 linewidth 5\n\
304set style line 18 dashtype 3 linewidth 5\n\
305set style line 19 dashtype 3 linewidth 5\n\
306set style line 20 dashtype 3 linewidth 5\n\
307set style line 21 dashtype 3 linewidth 5\n\
308set style line 22 dashtype 3 linewidth 5\n\
309set style line 23 dashtype 3 linewidth 5\n\
310set style line 24 dashtype 3 linewidth 5\n\
311set style line 25 dashtype 4 linewidth 5\n\
312set style line 26 dashtype 4 linewidth 5\n\
313set style line 27 dashtype 4 linewidth 5\n\
314set style line 28 dashtype 4 linewidth 5\n\
315set style line 29 dashtype 4 linewidth 5\n\
316set style line 30 dashtype 4 linewidth 5\n\
317set style line 31 dashtype 4 linewidth 5\n\
318set style line 32 dashtype 4 linewidth 5\n\
319set style increment user");
320 plot.GenerateOutput(file);
321 file.close();
322
323 return 0;
324}
a polymophic address class
Definition address.h:90
holds a vector of ns3::Application pointers.
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
void Stop(Time stop) const
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
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
Class to represent a 2D points plot.
Definition gnuplot.h:105
a simple class to generate gnuplot-ready plotting commands from a set of datasets.
Definition gnuplot.h:359
void AddDataset(const GnuplotDataset &dataset)
Definition gnuplot.cc:785
void SetLegend(const std::string &xLegend, const std::string &yLegend)
Definition gnuplot.cc:765
void SetTerminal(const std::string &terminal)
Definition gnuplot.cc:753
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
static uint64_t GetDataRate(uint8_t mcsValue, MHz_u channelWidth, Time guardInterval, uint8_t nss)
Return the data rate corresponding to the supplied HT MCS index, channel width, guard interval,...
Definition ht-phy.cc:687
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
static Ipv4Address GetAny()
static void PopulateRoutingTables()
Build a routing database and initialize the routing tables of the nodes in the simulation.
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
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.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
Smart pointer class similar to boost::intrusive_ptr.
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
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
Create a client application which sends UDP packets carrying a 32bit sequence number and a 64 bit tim...
Create a server application which waits for input UDP packets and uses the information carried into t...
Hold an unsigned integer type.
Definition uinteger.h:34
helps to create WifiNetDevice objects
create MAC layers for a ns3::WifiNetDevice.
manage and create wifi channel objects for the YANS model.
static YansWifiChannelHelper Default()
Create a channel helper in a default working state.
Make it easy to create and manage PHY objects for the YANS model.
uint16_t port
Definition dsdv-manet.cc:33
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:883
void Set(std::string path, const AttributeValue &value)
Definition config.cc:869
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
@ WIFI_STANDARD_80211n
address
Definition first.py:36
stack
Definition first.py:33
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
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
phy
Definition third.py:78
std::ofstream throughput