A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-80211n-mimo.cc
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation;
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 *
15 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
16 */
17
18// This example is used to validate 802.11n MIMO.
19//
20// It outputs plots of the throughput versus the distance
21// for every HT MCS value and from 1 to 4 MIMO streams.
22//
23// The simulation assumes a single station in an infrastructure network:
24//
25// STA AP
26// * *
27// | |
28// n1 n2
29//
30// The user can choose whether UDP or TCP should be used and can configure
31// some 802.11n parameters (frequency, channel width and guard interval).
32//
33// An important configuration parameter is preamble detection. It is enabled
34// by default (to match the default ns-3 configuration) but will dominate
35// performance at low SNRs, causing the different MCS to appear to have
36// the same range (because regardless of the MCS, the preamble detection
37// thresholds do not change).
38
39#include "ns3/boolean.h"
40#include "ns3/command-line.h"
41#include "ns3/config.h"
42#include "ns3/double.h"
43#include "ns3/gnuplot.h"
44#include "ns3/ht-phy.h"
45#include "ns3/internet-stack-helper.h"
46#include "ns3/ipv4-address-helper.h"
47#include "ns3/ipv4-global-routing-helper.h"
48#include "ns3/mobility-helper.h"
49#include "ns3/on-off-helper.h"
50#include "ns3/packet-sink-helper.h"
51#include "ns3/packet-sink.h"
52#include "ns3/ssid.h"
53#include "ns3/string.h"
54#include "ns3/udp-client-server-helper.h"
55#include "ns3/udp-server.h"
56#include "ns3/uinteger.h"
57#include "ns3/yans-wifi-channel.h"
58#include "ns3/yans-wifi-helper.h"
59
60using namespace ns3;
61
62int
63main(int argc, char* argv[])
64{
65 std::ofstream file("80211n-mimo-throughput.plt");
66
67 std::vector<std::string> modes = {
68 "HtMcs0", "HtMcs1", "HtMcs2", "HtMcs3", "HtMcs4", "HtMcs5", "HtMcs6", "HtMcs7",
69 "HtMcs8", "HtMcs9", "HtMcs10", "HtMcs11", "HtMcs12", "HtMcs13", "HtMcs14", "HtMcs15",
70 "HtMcs16", "HtMcs17", "HtMcs18", "HtMcs19", "HtMcs20", "HtMcs21", "HtMcs22", "HtMcs23",
71 "HtMcs24", "HtMcs25", "HtMcs26", "HtMcs27", "HtMcs28", "HtMcs29", "HtMcs30", "HtMcs31",
72 };
73
74 bool udp = true;
75 double simulationTime = 5; // seconds
76 double frequency = 5.0; // whether 2.4 or 5.0 GHz
77 double step = 5; // meters
78 bool shortGuardInterval = false;
79 bool channelBonding = false;
80 bool preambleDetection = true;
81
82 CommandLine cmd(__FILE__);
83 cmd.AddValue("step", "Granularity of the results to be plotted in meters", step);
84 cmd.AddValue("simulationTime", "Simulation time per step (in seconds)", simulationTime);
85 cmd.AddValue("channelBonding",
86 "Enable/disable channel bonding (channel width = 20 MHz if false, channel width = "
87 "40 MHz if true)",
88 channelBonding);
89 cmd.AddValue("preambleDetection", "Enable/disable preamble detection model", preambleDetection);
90 cmd.AddValue("shortGuardInterval", "Enable/disable short guard interval", shortGuardInterval);
91 cmd.AddValue("frequency",
92 "Whether working in the 2.4 or 5.0 GHz band (other values gets rejected)",
93 frequency);
94 cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp);
95 cmd.Parse(argc, argv);
96
97 Gnuplot plot = Gnuplot("80211n-mimo-throughput.eps");
98
99 for (uint32_t i = 0; i < modes.size(); i++) // MCS
100 {
101 std::cout << modes[i] << std::endl;
102 Gnuplot2dDataset dataset(modes[i]);
103 for (double d = 0; d <= 100;) // distance
104 {
105 std::cout << "Distance = " << d << "m: " << std::endl;
106 uint32_t payloadSize; // 1500 byte IP packet
107 if (udp)
108 {
109 payloadSize = 1472; // bytes
110 }
111 else
112 {
113 payloadSize = 1448; // bytes
114 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(payloadSize));
115 }
116
117 uint8_t nStreams = 1 + (i / 8); // number of MIMO streams
118
119 NodeContainer wifiStaNode;
120 wifiStaNode.Create(1);
122 wifiApNode.Create(1);
123
126 phy.SetChannel(channel.Create());
127 if (!preambleDetection)
128 {
129 phy.DisablePreambleDetectionModel();
130 }
131
132 // Set MIMO capabilities
133 phy.Set("Antennas", UintegerValue(nStreams));
134 phy.Set("MaxSupportedTxSpatialStreams", UintegerValue(nStreams));
135 phy.Set("MaxSupportedRxSpatialStreams", UintegerValue(nStreams));
136 phy.Set("ChannelSettings",
137 StringValue(std::string("{0, ") + (channelBonding ? "40, " : "20, ") +
138 (frequency == 2.4 ? "BAND_2_4GHZ" : "BAND_5GHZ") + ", 0}"));
139
142 if (frequency == 5.0)
143 {
144 wifi.SetStandard(WIFI_STANDARD_80211n);
145 }
146 else if (frequency == 2.4)
147 {
148 wifi.SetStandard(WIFI_STANDARD_80211n);
149 Config::SetDefault("ns3::LogDistancePropagationLossModel::ReferenceLoss",
150 DoubleValue(40.046));
151 }
152 else
153 {
154 std::cout << "Wrong frequency value!" << std::endl;
155 return 0;
156 }
157
158 StringValue ctrlRate;
159 if (frequency == 2.4)
160 {
161 ctrlRate = StringValue("ErpOfdmRate24Mbps");
162 }
163 else
164 {
165 ctrlRate = StringValue("OfdmRate24Mbps");
166 }
167 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
168 "DataMode",
169 StringValue(modes[i]),
170 "ControlMode",
171 ctrlRate);
172
173 Ssid ssid = Ssid("ns3-80211n");
174
175 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
176
177 NetDeviceContainer staDevice;
178 staDevice = wifi.Install(phy, mac, wifiStaNode);
179
180 mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
181
182 NetDeviceContainer apDevice;
183 apDevice = wifi.Install(phy, mac, wifiApNode);
184
185 // Set guard interval
186 Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/"
187 "ShortGuardIntervalSupported",
188 BooleanValue(shortGuardInterval));
189
190 // mobility.
192 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
193
194 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
195 positionAlloc->Add(Vector(d, 0.0, 0.0));
196 mobility.SetPositionAllocator(positionAlloc);
197
198 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
199
200 mobility.Install(wifiApNode);
201 mobility.Install(wifiStaNode);
202
203 /* Internet stack*/
205 stack.Install(wifiApNode);
206 stack.Install(wifiStaNode);
207
209 address.SetBase("192.168.1.0", "255.255.255.0");
210 Ipv4InterfaceContainer staNodeInterface;
211 Ipv4InterfaceContainer apNodeInterface;
212
213 staNodeInterface = address.Assign(staDevice);
214 apNodeInterface = address.Assign(apDevice);
215
216 /* Setting applications */
217 const auto maxLoad = HtPhy::GetDataRate(i,
218 channelBonding ? 40 : 20,
219 shortGuardInterval ? 400 : 800,
220 nStreams);
221 ApplicationContainer serverApp;
222 if (udp)
223 {
224 // UDP flow
225 uint16_t port = 9;
227 serverApp = server.Install(wifiStaNode.Get(0));
228 serverApp.Start(Seconds(0.0));
229 serverApp.Stop(Seconds(simulationTime + 1));
230 const auto packetInterval = payloadSize * 8.0 / maxLoad;
231
232 UdpClientHelper client(staNodeInterface.GetAddress(0), port);
233 client.SetAttribute("MaxPackets", UintegerValue(4294967295U));
234 client.SetAttribute("Interval", TimeValue(Seconds(packetInterval)));
235 client.SetAttribute("PacketSize", UintegerValue(payloadSize));
236 ApplicationContainer clientApp = client.Install(wifiApNode.Get(0));
237 clientApp.Start(Seconds(1.0));
238 clientApp.Stop(Seconds(simulationTime + 1));
239 }
240 else
241 {
242 // TCP flow
243 uint16_t port = 50000;
245 PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress);
246 serverApp = packetSinkHelper.Install(wifiStaNode.Get(0));
247 serverApp.Start(Seconds(0.0));
248 serverApp.Stop(Seconds(simulationTime + 1));
249
250 OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny());
251 onoff.SetAttribute("OnTime",
252 StringValue("ns3::ConstantRandomVariable[Constant=1]"));
253 onoff.SetAttribute("OffTime",
254 StringValue("ns3::ConstantRandomVariable[Constant=0]"));
255 onoff.SetAttribute("PacketSize", UintegerValue(payloadSize));
256 onoff.SetAttribute("DataRate", DataRateValue(maxLoad));
258 onoff.SetAttribute("Remote", remoteAddress);
259 ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0));
260 clientApp.Start(Seconds(1.0));
261 clientApp.Stop(Seconds(simulationTime + 1));
262 }
263
265
266 Simulator::Stop(Seconds(simulationTime + 1));
268
269 double throughput = 0;
270 if (udp)
271 {
272 // UDP
273 uint64_t totalPacketsThrough =
274 DynamicCast<UdpServer>(serverApp.Get(0))->GetReceived();
275 throughput =
276 totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); // Mbit/s
277 }
278 else
279 {
280 // TCP
281 uint64_t totalPacketsThrough =
282 DynamicCast<PacketSink>(serverApp.Get(0))->GetTotalRx();
283 throughput = totalPacketsThrough * 8 / (simulationTime * 1000000.0); // Mbit/s
284 }
285 dataset.Add(d, throughput);
286 std::cout << throughput << " Mbit/s" << std::endl;
287 d += step;
289 }
290 plot.AddDataset(dataset);
291 }
292
293 plot.SetTerminal("postscript eps color enh \"Times-BoldItalic\"");
294 plot.SetLegend("Distance (Meters)", "Throughput (Mbit/s)");
295 plot.SetExtra("set xrange [0:100]\n\
296set yrange [0:600]\n\
297set ytics 0,50,600\n\
298set style line 1 dashtype 1 linewidth 5\n\
299set style line 2 dashtype 1 linewidth 5\n\
300set style line 3 dashtype 1 linewidth 5\n\
301set style line 4 dashtype 1 linewidth 5\n\
302set style line 5 dashtype 1 linewidth 5\n\
303set style line 6 dashtype 1 linewidth 5\n\
304set style line 7 dashtype 1 linewidth 5\n\
305set style line 8 dashtype 1 linewidth 5\n\
306set style line 9 dashtype 2 linewidth 5\n\
307set style line 10 dashtype 2 linewidth 5\n\
308set style line 11 dashtype 2 linewidth 5\n\
309set style line 12 dashtype 2 linewidth 5\n\
310set style line 13 dashtype 2 linewidth 5\n\
311set style line 14 dashtype 2 linewidth 5\n\
312set style line 15 dashtype 2 linewidth 5\n\
313set style line 16 dashtype 2 linewidth 5\n\
314set style line 17 dashtype 3 linewidth 5\n\
315set style line 18 dashtype 3 linewidth 5\n\
316set style line 19 dashtype 3 linewidth 5\n\
317set style line 20 dashtype 3 linewidth 5\n\
318set style line 21 dashtype 3 linewidth 5\n\
319set style line 22 dashtype 3 linewidth 5\n\
320set style line 23 dashtype 3 linewidth 5\n\
321set style line 24 dashtype 3 linewidth 5\n\
322set style line 25 dashtype 4 linewidth 5\n\
323set style line 26 dashtype 4 linewidth 5\n\
324set style line 27 dashtype 4 linewidth 5\n\
325set style line 28 dashtype 4 linewidth 5\n\
326set style line 29 dashtype 4 linewidth 5\n\
327set style line 30 dashtype 4 linewidth 5\n\
328set style line 31 dashtype 4 linewidth 5\n\
329set style line 32 dashtype 4 linewidth 5\n\
330set style increment user");
331 plot.GenerateOutput(file);
332 file.close();
333
334 return 0;
335}
a polymophic address class
Definition: address.h:101
AttributeValue implementation for Address.
Definition: address.h:286
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.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Parse command-line arguments.
Definition: command-line.h:232
AttributeValue implementation for DataRate.
Definition: data-rate.h:296
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Class to represent a 2D points plot.
Definition: gnuplot.h:116
a simple class to generate gnuplot-ready plotting commands from a set of datasets.
Definition: gnuplot.h:370
void AddDataset(const GnuplotDataset &dataset)
Definition: gnuplot.cc:796
void SetLegend(const std::string &xLegend, const std::string &yLegend)
Definition: gnuplot.cc:776
void SetTerminal(const std::string &terminal)
Definition: gnuplot.cc:764
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
static uint64_t GetDataRate(uint8_t mcsValue, uint16_t channelWidth, uint16_t guardInterval, uint8_t nss)
Return the data rate corresponding to the supplied HT MCS index, channel width, guard interval,...
Definition: ht-phy.cc:696
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.
Definition: on-off-helper.h:37
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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
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
AttributeValue implementation for Time.
Definition: nstime.h:1406
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:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
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:44
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:894
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:880
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
@ WIFI_STANDARD_80211n
ns address
Definition: first.py:47
ns stack
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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
ns phy
Definition: third.py:89
std::ofstream throughput