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