A Discrete-Event Network Simulator
QKDNetSim v2.0 (NS-3 v3.41) @ (+)
API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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/internet-stack-helper.h"
45 #include "ns3/ipv4-address-helper.h"
46 #include "ns3/ipv4-global-routing-helper.h"
47 #include "ns3/mobility-helper.h"
48 #include "ns3/on-off-helper.h"
49 #include "ns3/packet-sink-helper.h"
50 #include "ns3/packet-sink.h"
51 #include "ns3/ssid.h"
52 #include "ns3/string.h"
53 #include "ns3/udp-client-server-helper.h"
54 #include "ns3/udp-server.h"
55 #include "ns3/uinteger.h"
56 #include "ns3/yans-wifi-channel.h"
57 #include "ns3/yans-wifi-helper.h"
58 
59 using namespace ns3;
60 
61 int
62 main(int argc, char* argv[])
63 {
64  std::ofstream file("80211n-mimo-throughput.plt");
65 
66  std::vector<std::string> modes = {
67  "HtMcs0", "HtMcs1", "HtMcs2", "HtMcs3", "HtMcs4", "HtMcs5", "HtMcs6", "HtMcs7",
68  "HtMcs8", "HtMcs9", "HtMcs10", "HtMcs11", "HtMcs12", "HtMcs13", "HtMcs14", "HtMcs15",
69  "HtMcs16", "HtMcs17", "HtMcs18", "HtMcs19", "HtMcs20", "HtMcs21", "HtMcs22", "HtMcs23",
70  "HtMcs24", "HtMcs25", "HtMcs26", "HtMcs27", "HtMcs28", "HtMcs29", "HtMcs30", "HtMcs31",
71  };
72 
73  bool udp = true;
74  double simulationTime = 5; // seconds
75  double frequency = 5.0; // whether 2.4 or 5.0 GHz
76  double step = 5; // meters
77  bool shortGuardInterval = false;
78  bool channelBonding = false;
79  bool preambleDetection = true;
80 
81  CommandLine cmd(__FILE__);
82  cmd.AddValue("step", "Granularity of the results to be plotted in meters", step);
83  cmd.AddValue("simulationTime", "Simulation time per step (in seconds)", simulationTime);
84  cmd.AddValue("channelBonding",
85  "Enable/disable channel bonding (channel width = 20 MHz if false, channel width = "
86  "40 MHz if true)",
87  channelBonding);
88  cmd.AddValue("preambleDetection", "Enable/disable preamble detection model", preambleDetection);
89  cmd.AddValue("shortGuardInterval", "Enable/disable short guard interval", shortGuardInterval);
90  cmd.AddValue("frequency",
91  "Whether working in the 2.4 or 5.0 GHz band (other values gets rejected)",
92  frequency);
93  cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp);
94  cmd.Parse(argc, argv);
95 
96  Gnuplot plot = Gnuplot("80211n-mimo-throughput.eps");
97 
98  for (uint32_t i = 0; i < modes.size(); i++) // MCS
99  {
100  std::cout << modes[i] << std::endl;
101  Gnuplot2dDataset dataset(modes[i]);
102  for (double d = 0; d <= 100;) // distance
103  {
104  std::cout << "Distance = " << d << "m: " << std::endl;
105  uint32_t payloadSize; // 1500 byte IP packet
106  if (udp)
107  {
108  payloadSize = 1472; // bytes
109  }
110  else
111  {
112  payloadSize = 1448; // bytes
113  Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(payloadSize));
114  }
115 
116  uint8_t nStreams = 1 + (i / 8); // number of MIMO streams
117 
118  NodeContainer wifiStaNode;
119  wifiStaNode.Create(1);
121  wifiApNode.Create(1);
122 
125  phy.SetChannel(channel.Create());
126  if (!preambleDetection)
127  {
128  phy.DisablePreambleDetectionModel();
129  }
130 
131  // Set MIMO capabilities
132  phy.Set("Antennas", UintegerValue(nStreams));
133  phy.Set("MaxSupportedTxSpatialStreams", UintegerValue(nStreams));
134  phy.Set("MaxSupportedRxSpatialStreams", UintegerValue(nStreams));
135  phy.Set("ChannelSettings",
136  StringValue(std::string("{0, ") + (channelBonding ? "40, " : "20, ") +
137  (frequency == 2.4 ? "BAND_2_4GHZ" : "BAND_5GHZ") + ", 0}"));
138 
141  if (frequency == 5.0)
142  {
143  wifi.SetStandard(WIFI_STANDARD_80211n);
144  }
145  else if (frequency == 2.4)
146  {
147  wifi.SetStandard(WIFI_STANDARD_80211n);
148  Config::SetDefault("ns3::LogDistancePropagationLossModel::ReferenceLoss",
149  DoubleValue(40.046));
150  }
151  else
152  {
153  std::cout << "Wrong frequency value!" << std::endl;
154  return 0;
155  }
156 
157  StringValue ctrlRate;
158  if (frequency == 2.4)
159  {
160  ctrlRate = StringValue("ErpOfdmRate24Mbps");
161  }
162  else
163  {
164  ctrlRate = StringValue("OfdmRate24Mbps");
165  }
166  wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
167  "DataMode",
168  StringValue(modes[i]),
169  "ControlMode",
170  ctrlRate);
171 
172  Ssid ssid = Ssid("ns3-80211n");
173 
174  mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
175 
176  NetDeviceContainer staDevice;
177  staDevice = wifi.Install(phy, mac, wifiStaNode);
178 
179  mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
180 
181  NetDeviceContainer apDevice;
182  apDevice = wifi.Install(phy, mac, wifiApNode);
183 
184  // Set guard interval
185  Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/"
186  "ShortGuardIntervalSupported",
187  BooleanValue(shortGuardInterval));
188 
189  // mobility.
191  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
192 
193  positionAlloc->Add(Vector(0.0, 0.0, 0.0));
194  positionAlloc->Add(Vector(d, 0.0, 0.0));
195  mobility.SetPositionAllocator(positionAlloc);
196 
197  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
198 
199  mobility.Install(wifiApNode);
200  mobility.Install(wifiStaNode);
201 
202  /* Internet stack*/
204  stack.Install(wifiApNode);
205  stack.Install(wifiStaNode);
206 
208  address.SetBase("192.168.1.0", "255.255.255.0");
209  Ipv4InterfaceContainer staNodeInterface;
210  Ipv4InterfaceContainer apNodeInterface;
211 
212  staNodeInterface = address.Assign(staDevice);
213  apNodeInterface = address.Assign(apDevice);
214 
215  /* Setting applications */
216  ApplicationContainer serverApp;
217  if (udp)
218  {
219  // UDP flow
220  uint16_t port = 9;
222  serverApp = server.Install(wifiStaNode.Get(0));
223  serverApp.Start(Seconds(0.0));
224  serverApp.Stop(Seconds(simulationTime + 1));
225 
226  UdpClientHelper client(staNodeInterface.GetAddress(0), port);
227  client.SetAttribute("MaxPackets", UintegerValue(4294967295U));
228  client.SetAttribute("Interval", TimeValue(Time("0.00001"))); // packets/s
229  client.SetAttribute("PacketSize", UintegerValue(payloadSize));
230  ApplicationContainer clientApp = client.Install(wifiApNode.Get(0));
231  clientApp.Start(Seconds(1.0));
232  clientApp.Stop(Seconds(simulationTime + 1));
233  }
234  else
235  {
236  // TCP flow
237  uint16_t port = 50000;
239  PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress);
240  serverApp = packetSinkHelper.Install(wifiStaNode.Get(0));
241  serverApp.Start(Seconds(0.0));
242  serverApp.Stop(Seconds(simulationTime + 1));
243 
244  OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny());
245  onoff.SetAttribute("OnTime",
246  StringValue("ns3::ConstantRandomVariable[Constant=1]"));
247  onoff.SetAttribute("OffTime",
248  StringValue("ns3::ConstantRandomVariable[Constant=0]"));
249  onoff.SetAttribute("PacketSize", UintegerValue(payloadSize));
250  onoff.SetAttribute("DataRate", DataRateValue(1000000000)); // bit/s
251  AddressValue remoteAddress(InetSocketAddress(staNodeInterface.GetAddress(0), port));
252  onoff.SetAttribute("Remote", remoteAddress);
253  ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0));
254  clientApp.Start(Seconds(1.0));
255  clientApp.Stop(Seconds(simulationTime + 1));
256  }
257 
259 
260  Simulator::Stop(Seconds(simulationTime + 1));
261  Simulator::Run();
262 
263  double throughput = 0;
264  if (udp)
265  {
266  // UDP
267  uint64_t totalPacketsThrough =
268  DynamicCast<UdpServer>(serverApp.Get(0))->GetReceived();
269  throughput =
270  totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); // Mbit/s
271  }
272  else
273  {
274  // TCP
275  uint64_t totalPacketsThrough =
276  DynamicCast<PacketSink>(serverApp.Get(0))->GetTotalRx();
277  throughput = totalPacketsThrough * 8 / (simulationTime * 1000000.0); // Mbit/s
278  }
279  dataset.Add(d, throughput);
280  std::cout << throughput << " Mbit/s" << std::endl;
281  d += step;
283  }
284  plot.AddDataset(dataset);
285  }
286 
287  plot.SetTerminal("postscript eps color enh \"Times-BoldItalic\"");
288  plot.SetLegend("Distance (Meters)", "Throughput (Mbit/s)");
289  plot.SetExtra("set xrange [0:100]\n\
290 set yrange [0:600]\n\
291 set ytics 0,50,600\n\
292 set style line 1 dashtype 1 linewidth 5\n\
293 set style line 2 dashtype 1 linewidth 5\n\
294 set style line 3 dashtype 1 linewidth 5\n\
295 set style line 4 dashtype 1 linewidth 5\n\
296 set style line 5 dashtype 1 linewidth 5\n\
297 set style line 6 dashtype 1 linewidth 5\n\
298 set style line 7 dashtype 1 linewidth 5\n\
299 set style line 8 dashtype 1 linewidth 5\n\
300 set style line 9 dashtype 2 linewidth 5\n\
301 set style line 10 dashtype 2 linewidth 5\n\
302 set style line 11 dashtype 2 linewidth 5\n\
303 set style line 12 dashtype 2 linewidth 5\n\
304 set style line 13 dashtype 2 linewidth 5\n\
305 set style line 14 dashtype 2 linewidth 5\n\
306 set style line 15 dashtype 2 linewidth 5\n\
307 set style line 16 dashtype 2 linewidth 5\n\
308 set style line 17 dashtype 3 linewidth 5\n\
309 set style line 18 dashtype 3 linewidth 5\n\
310 set style line 19 dashtype 3 linewidth 5\n\
311 set style line 20 dashtype 3 linewidth 5\n\
312 set style line 21 dashtype 3 linewidth 5\n\
313 set style line 22 dashtype 3 linewidth 5\n\
314 set style line 23 dashtype 3 linewidth 5\n\
315 set style line 24 dashtype 3 linewidth 5\n\
316 set style line 25 dashtype 4 linewidth 5\n\
317 set style line 26 dashtype 4 linewidth 5\n\
318 set style line 27 dashtype 4 linewidth 5\n\
319 set style line 28 dashtype 4 linewidth 5\n\
320 set style line 29 dashtype 4 linewidth 5\n\
321 set style line 30 dashtype 4 linewidth 5\n\
322 set style line 31 dashtype 4 linewidth 5\n\
323 set style line 32 dashtype 4 linewidth 5\n\
324 set style increment user");
325  plot.GenerateOutput(file);
326  file.close();
327 
328  return 0;
329 }
a polymophic address class
Definition: address.h:101
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.
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
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:373
void AddDataset(const GnuplotDataset &dataset)
Definition: gnuplot.cc:759
void SetLegend(const std::string &xLegend, const std::string &yLegend)
Definition: gnuplot.cc:739
void SetTerminal(const std::string &terminal)
Definition: gnuplot.cc:727
void GenerateOutput(std::ostream &os)
Writes gnuplot commands and data values to a single output stream.
Definition: gnuplot.cc:765
void SetExtra(const std::string &extra)
Definition: gnuplot.cc:746
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:44
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
Hold variables of type string.
Definition: string.h:56
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:890
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:876
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
@ WIFI_STANDARD_80211n
address
Definition: first.py:47
stack
Definition: first.py:44
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:839
Every class exported by the ns3 library is enclosed in the ns3 namespace.
cmd
Definition: second.py:40
ssid
Definition: third.py:93
channel
Definition: third.py:88
mac
Definition: third.py:92
wifi
Definition: third.py:95
wifiApNode
Definition: third.py:86
mobility
Definition: third.py:105
phy
Definition: third.py:89
std::ofstream throughput