A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-rate-adaptation-distance.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 Universidad de la República - Uruguay
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: Matías Richart <mrichart@fing.edu.uy>
18 */
19
20/**
21 * This example program is designed to illustrate the behavior of
22 * rate-adaptive WiFi rate controls such as Minstrel. Power-adaptive
23 * rate controls can be illustrated also, but separate examples exist for
24 * highlighting the power adaptation.
25 *
26 * This simulation consist of 2 nodes, one AP and one STA.
27 * The AP generates UDP traffic with a CBR of 400 Mbps to the STA.
28 * The AP can use any power and rate control mechanism and the STA uses
29 * only Minstrel rate control.
30 * The STA can be configured to move away from (or towards to) the AP.
31 * By default, the AP is at coordinate (0,0,0) and the STA starts at
32 * coordinate (5,0,0) (meters) and moves away on the x axis by 1 meter every
33 * second.
34 *
35 * The output consists of:
36 * - A plot of average throughput vs. distance.
37 * - (if logging is enabled) the changes of rate to standard output.
38 *
39 * Example usage:
40 * ./ns3 run "wifi-rate-adaptation-distance --standard=802.11a --staManager=ns3::MinstrelWifiManager
41 * --apManager=ns3::MinstrelWifiManager --outputFileName=minstrel"
42 *
43 * Another example (moving towards the AP):
44 * ./ns3 run "wifi-rate-adaptation-distance --standard=802.11a --staManager=ns3::MinstrelWifiManager
45 * --apManager=ns3::MinstrelWifiManager --outputFileName=minstrel --stepsSize=1 --STA1_x=-200"
46 *
47 * Example for HT rates with SGI and channel width of 40MHz:
48 * ./ns3 run "wifi-rate-adaptation-distance --staManager=ns3::MinstrelHtWifiManager
49 * --apManager=ns3::MinstrelHtWifiManager --outputFileName=minstrelHt --shortGuardInterval=true
50 * --channelWidth=40"
51 *
52 * To enable the log of rate changes:
53 * export NS_LOG=RateAdaptationDistance=level_info
54 */
55
56#include "ns3/boolean.h"
57#include "ns3/command-line.h"
58#include "ns3/config.h"
59#include "ns3/double.h"
60#include "ns3/gnuplot.h"
61#include "ns3/internet-stack-helper.h"
62#include "ns3/ipv4-address-helper.h"
63#include "ns3/log.h"
64#include "ns3/mobility-helper.h"
65#include "ns3/mobility-model.h"
66#include "ns3/on-off-helper.h"
67#include "ns3/packet-sink-helper.h"
68#include "ns3/ssid.h"
69#include "ns3/string.h"
70#include "ns3/uinteger.h"
71#include "ns3/yans-wifi-channel.h"
72#include "ns3/yans-wifi-helper.h"
73
74using namespace ns3;
75
76NS_LOG_COMPONENT_DEFINE("RateAdaptationDistance");
77
78/** Node statistics */
80{
81 public:
82 /**
83 * Constructor
84 * \param aps AP devices
85 * \param stas STA devices
86 */
88
89 /**
90 * RX callback
91 * \param path path
92 * \param packet received packet
93 * \param from sender
94 */
95 void RxCallback(std::string path, Ptr<const Packet> packet, const Address& from);
96 /**
97 * Set node position
98 * \param node the node
99 * \param position the position
100 */
101 void SetPosition(Ptr<Node> node, Vector position);
102 /**
103 * Advance node position
104 * \param node the node
105 * \param stepsSize the size of a step
106 * \param stepsTime the time interval between steps
107 */
108 void AdvancePosition(Ptr<Node> node, int stepsSize, int stepsTime);
109 /**
110 * Get node position
111 * \param node the node
112 * \return the position
113 */
114 Vector GetPosition(Ptr<Node> node);
115 /**
116 * \return the gnuplot 2d dataset
117 */
119
120 private:
121 uint32_t m_bytesTotal; //!< total bytes
122 Gnuplot2dDataset m_output; //!< gnuplot 2d dataset
123};
124
126{
127 m_bytesTotal = 0;
128}
129
130void
131NodeStatistics::RxCallback(std::string path, Ptr<const Packet> packet, const Address& from)
132{
133 m_bytesTotal += packet->GetSize();
134}
135
136void
137NodeStatistics::SetPosition(Ptr<Node> node, Vector position)
138{
139 Ptr<MobilityModel> mobility = node->GetObject<MobilityModel>();
140 mobility->SetPosition(position);
141}
142
143Vector
145{
146 Ptr<MobilityModel> mobility = node->GetObject<MobilityModel>();
147 return mobility->GetPosition();
148}
149
150void
151NodeStatistics::AdvancePosition(Ptr<Node> node, int stepsSize, int stepsTime)
152{
153 Vector pos = GetPosition(node);
154 double mbs = ((m_bytesTotal * 8.0) / (1000000 * stepsTime));
155 m_bytesTotal = 0;
156 m_output.Add(pos.x, mbs);
157 pos.x += stepsSize;
158 SetPosition(node, pos);
159 Simulator::Schedule(Seconds(stepsTime),
161 this,
162 node,
163 stepsSize,
164 stepsTime);
165}
166
169{
170 return m_output;
171}
172
173/**
174 * Callback for 'Rate' trace source
175 *
176 * \param oldRate old MCS rate (bits/sec)
177 * \param newRate new MCS rate (bits/sec)
178 */
179void
180RateCallback(uint64_t oldRate, uint64_t newRate)
181{
182 NS_LOG_INFO("Rate " << newRate / 1000000.0 << " Mbps");
183}
184
185int
186main(int argc, char* argv[])
187{
188 uint32_t rtsThreshold = 65535;
189 std::string staManager = "ns3::MinstrelHtWifiManager";
190 std::string apManager = "ns3::MinstrelHtWifiManager";
191 std::string standard = "802.11n-5GHz";
192 std::string outputFileName = "minstrelHT";
193 uint32_t BeMaxAmpduSize = 65535;
194 bool shortGuardInterval = false;
195 uint32_t chWidth = 20;
196 int ap1_x = 0;
197 int ap1_y = 0;
198 int sta1_x = 5;
199 int sta1_y = 0;
200 int steps = 100;
201 int stepsSize = 1;
202 int stepsTime = 1;
203
204 CommandLine cmd(__FILE__);
205 cmd.AddValue("staManager", "Rate adaptation manager of the STA", staManager);
206 cmd.AddValue("apManager", "Rate adaptation manager of the AP", apManager);
207 cmd.AddValue("standard", "Wifi standard (a/b/g/n/ac only)", standard);
208 cmd.AddValue("shortGuardInterval",
209 "Enable Short Guard Interval in all stations",
210 shortGuardInterval);
211 cmd.AddValue("channelWidth", "Channel width of all the stations", chWidth);
212 cmd.AddValue("rtsThreshold", "RTS threshold", rtsThreshold);
213 cmd.AddValue("BeMaxAmpduSize", "BE Mac A-MPDU size", BeMaxAmpduSize);
214 cmd.AddValue("outputFileName", "Output filename", outputFileName);
215 cmd.AddValue("steps", "How many different distances to try", steps);
216 cmd.AddValue("stepsTime", "Time on each step", stepsTime);
217 cmd.AddValue("stepsSize", "Distance between steps", stepsSize);
218 cmd.AddValue("AP1_x", "Position of AP1 in x coordinate", ap1_x);
219 cmd.AddValue("AP1_y", "Position of AP1 in y coordinate", ap1_y);
220 cmd.AddValue("STA1_x", "Position of STA1 in x coordinate", sta1_x);
221 cmd.AddValue("STA1_y", "Position of STA1 in y coordinate", sta1_y);
222 cmd.Parse(argc, argv);
223
224 int simuTime = steps * stepsTime;
225
226 if (standard != "802.11a" && standard != "802.11b" && standard != "802.11g" &&
227 standard != "802.11n-2.4GHz" && standard != "802.11n-5GHz" && standard != "802.11ac")
228 {
229 NS_FATAL_ERROR("Standard " << standard << " is not supported by this program");
230 }
231
232 // Define the APs
233 NodeContainer wifiApNodes;
234 wifiApNodes.Create(1);
235
236 // Define the STAs
238 wifiStaNodes.Create(1);
239
240 YansWifiPhyHelper wifiPhy;
242 wifiPhy.SetChannel(wifiChannel.Create());
243 // Channel configuration via ChannelSettings attribute can be performed here
244 std::string frequencyBand;
245 if (standard == "802.11b" || standard == "802.11g" || standard == "802.11n-2.4GHz")
246 {
247 frequencyBand = "BAND_2_4GHZ";
248 }
249 else
250 {
251 frequencyBand = "BAND_5GHZ";
252 }
253 wifiPhy.Set("ChannelSettings",
254 StringValue("{0, " + std::to_string(chWidth) + ", " + frequencyBand + ", 0}"));
255
256 // By default, the CCA sensitivity is -82 dBm, meaning if the RSS is
257 // below this value, the receiver will reject the Wi-Fi frame.
258 // However, we want to allow the rate adaptation to work down to low
259 // SNR values. To allow this, we need to do three things: 1) disable
260 // the noise figure (set it to 0 dB) so that the noise level in 20 MHz
261 // is around -101 dBm, 2) lower the CCA sensitivity to a value that
262 // disables it (e.g. -110 dBm), and 3) disable the Wi-Fi preamble
263 // detection model.
264 wifiPhy.Set("CcaSensitivity", DoubleValue(-110));
265 wifiPhy.Set("RxNoiseFigure", DoubleValue(0));
267
268 NetDeviceContainer wifiApDevices;
269 NetDeviceContainer wifiStaDevices;
270 NetDeviceContainer wifiDevices;
271
273 if (standard == "802.11a" || standard == "802.11b" || standard == "802.11g")
274 {
275 if (standard == "802.11a")
276 {
277 wifi.SetStandard(WIFI_STANDARD_80211a);
278 }
279 else if (standard == "802.11b")
280 {
281 wifi.SetStandard(WIFI_STANDARD_80211b);
282 }
283 else if (standard == "802.11g")
284 {
285 wifi.SetStandard(WIFI_STANDARD_80211g);
286 }
287 WifiMacHelper wifiMac;
288
289 // Configure the STA node
290 wifi.SetRemoteStationManager(staManager, "RtsCtsThreshold", UintegerValue(rtsThreshold));
291
292 Ssid ssid = Ssid("AP");
293 wifiMac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
294 wifiStaDevices.Add(wifi.Install(wifiPhy, wifiMac, wifiStaNodes.Get(0)));
295
296 // Configure the AP node
297 wifi.SetRemoteStationManager(apManager, "RtsCtsThreshold", UintegerValue(rtsThreshold));
298
299 ssid = Ssid("AP");
300 wifiMac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
301 wifiApDevices.Add(wifi.Install(wifiPhy, wifiMac, wifiApNodes.Get(0)));
302 }
303 else if (standard == "802.11n-2.4GHz" || standard == "802.11n-5GHz" || standard == "802.11ac")
304 {
305 if (standard == "802.11n-2.4GHz" || standard == "802.11n-5GHz")
306 {
307 wifi.SetStandard(WIFI_STANDARD_80211n);
308 }
309 else if (standard == "802.11ac")
310 {
311 wifi.SetStandard(WIFI_STANDARD_80211ac);
312 }
313
314 WifiMacHelper wifiMac;
315
316 // Configure the STA node
317 wifi.SetRemoteStationManager(staManager, "RtsCtsThreshold", UintegerValue(rtsThreshold));
318
319 Ssid ssid = Ssid("AP");
320 wifiMac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
321 wifiStaDevices.Add(wifi.Install(wifiPhy, wifiMac, wifiStaNodes.Get(0)));
322
323 // Configure the AP node
324 wifi.SetRemoteStationManager(apManager, "RtsCtsThreshold", UintegerValue(rtsThreshold));
325
326 ssid = Ssid("AP");
327 wifiMac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
328 wifiApDevices.Add(wifi.Install(wifiPhy, wifiMac, wifiApNodes.Get(0)));
329
330 Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
331 UintegerValue(BeMaxAmpduSize));
332 }
333
334 wifiDevices.Add(wifiStaDevices);
335 wifiDevices.Add(wifiApDevices);
336
337 // Set guard interval
339 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/ShortGuardIntervalSupported",
340 BooleanValue(shortGuardInterval));
341
342 // Configure the mobility.
344 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
345 // Initial position of AP and STA
346 positionAlloc->Add(Vector(ap1_x, ap1_y, 0.0));
347 positionAlloc->Add(Vector(sta1_x, sta1_y, 0.0));
348 mobility.SetPositionAllocator(positionAlloc);
349 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
350 mobility.Install(wifiApNodes.Get(0));
351 mobility.Install(wifiStaNodes.Get(0));
352
353 // Statistics counter
354 NodeStatistics atpCounter = NodeStatistics(wifiApDevices, wifiStaDevices);
355
356 // Move the STA by stepsSize meters every stepsTime seconds
357 Simulator::Schedule(Seconds(0.5 + stepsTime),
359 &atpCounter,
360 wifiStaNodes.Get(0),
361 stepsSize,
362 stepsTime);
363
364 // Configure the IP stack
366 stack.Install(wifiApNodes);
367 stack.Install(wifiStaNodes);
369 address.SetBase("10.1.1.0", "255.255.255.0");
370 Ipv4InterfaceContainer i = address.Assign(wifiDevices);
371 Ipv4Address sinkAddress = i.GetAddress(0);
372 uint16_t port = 9;
373
374 // Configure the CBR generator
375 PacketSinkHelper sink("ns3::UdpSocketFactory", InetSocketAddress(sinkAddress, port));
376 ApplicationContainer apps_sink = sink.Install(wifiStaNodes.Get(0));
377
378 OnOffHelper onoff("ns3::UdpSocketFactory", InetSocketAddress(sinkAddress, port));
379 onoff.SetConstantRate(DataRate("400Mb/s"), 1420);
380 onoff.SetAttribute("StartTime", TimeValue(Seconds(0.5)));
381 onoff.SetAttribute("StopTime", TimeValue(Seconds(simuTime)));
382 ApplicationContainer apps_source = onoff.Install(wifiApNodes.Get(0));
383
384 apps_sink.Start(Seconds(0.5));
385 apps_sink.Stop(Seconds(simuTime));
386
387 //------------------------------------------------------------
388 //-- Setup stats and data collection
389 //--------------------------------------------
390
391 // Register packet receptions to calculate throughput
392 Config::Connect("/NodeList/1/ApplicationList/*/$ns3::PacketSink/Rx",
394
395 // Callbacks to print every change of rate
397 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$" + apManager + "/Rate",
399
400 Simulator::Stop(Seconds(simuTime));
402
403 std::ofstream outfile("throughput-" + outputFileName + ".plt");
404 Gnuplot gnuplot = Gnuplot("throughput-" + outputFileName + ".eps", "Throughput");
405 gnuplot.SetTerminal("post eps color enhanced");
406 gnuplot.SetLegend("Distance (meters)", "Throughput (Mb/s)");
407 gnuplot.SetTitle("Throughput (AP to STA) vs distance");
408 gnuplot.AddDataset(atpCounter.GetDatafile());
409 gnuplot.GenerateOutput(outfile);
410
412
413 return 0;
414}
Class to collect node statistics.
void SetPosition(Ptr< Node > node, Vector position)
Set node position.
Gnuplot2dDataset GetDatafile()
void RxCallback(std::string path, Ptr< const Packet > packet, const Address &from)
RX callback.
NodeStatistics(NetDeviceContainer aps, NetDeviceContainer stas)
Constructor.
uint32_t m_bytesTotal
Number of received bytes on a given state.
Vector GetPosition(Ptr< Node > node)
Get node position.
Gnuplot2dDataset m_output
Throughput output data.
void AdvancePosition(Ptr< Node > node, int stepsSize, int stepsTime)
Advance node position.
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.
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
Class for representing data rates.
Definition: data-rate.h:89
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
void Add(double x, double y)
Definition: gnuplot.cc:377
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 SetTitle(const std::string &title)
Definition: gnuplot.cc:770
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.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
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.
Keep track of the current position and velocity of an object.
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
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 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
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
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 SetType(std::string type, Args &&... args)
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:163
void DisablePreambleDetectionModel()
Disable the preamble detection model on all links.
Definition: wifi-helper.cc:178
manage and create wifi channel objects for the YANS model.
static YansWifiChannelHelper Default()
Create a channel helper in a default working state.
Ptr< YansWifiChannel > Create() const
Make it easy to create and manage PHY objects for the YANS model.
void SetChannel(Ptr< YansWifiChannel > channel)
uint16_t port
Definition: dsdv-manet.cc:44
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:978
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:880
bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:964
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211g
@ WIFI_STANDARD_80211ac
@ WIFI_STANDARD_80211b
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.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:706
ns cmd
Definition: second.py:40
ns wifi
Definition: third.py:95
ns ssid
Definition: third.py:93
ns mobility
Definition: third.py:105
ns wifiStaNodes
Definition: third.py:84
void RateCallback(uint64_t oldRate, uint64_t newRate)
Callback for 'Rate' trace source.
Ptr< PacketSink > sink
Pointer to the packet sink application.
Definition: wifi-tcp.cc:55