A Discrete-Event Network Simulator
API
wifi-manager-example.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2016 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Tom Henderson <tomhend@u.washington.edu>
19  * Matías Richart <mrichart@fing.edu.uy>
20  * Sébastien Deronne <sebastien.deronne@gmail.com>
21  */
22 
23 // Test the operation of a wifi manager as the SNR is varied, and create
24 // a gnuplot output file for plotting.
25 //
26 // The test consists of a device acting as server and a device as client generating traffic.
27 //
28 // The output consists of a plot of the rate observed and selected at the client device.
29 //
30 // By default, the 802.11a standard using IdealWifiManager is plotted. Several command line
31 // arguments can change the following options:
32 // --wifiManager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, MinstrelHt, Onoe, Rraa, ThompsonSampling)
33 // --standard (802.11a, 802.11b, 802.11g, 802.11p-10MHz, 802.11p-5MHz, 802.11n-5GHz, 802.11n-2.4GHz, 802.11ac, 802.11ax-6GHz, 802.11ax-5GHz, 802.11ax-2.4GHz)
34 // --serverShortGuardInterval and --clientShortGuardInterval (for 802.11n/ac)
35 // --serverNss and --clientNss (for 802.11n/ac)
36 // --serverChannelWidth and --clientChannelWidth (for 802.11n/ac)
37 // --broadcast instead of unicast (default is unicast)
38 // --rtsThreshold (by default, value of 99999 disables it)
39 
40 #include "ns3/log.h"
41 #include "ns3/config.h"
42 #include "ns3/uinteger.h"
43 #include "ns3/boolean.h"
44 #include "ns3/double.h"
45 #include "ns3/enum.h"
46 #include "ns3/tuple.h"
47 #include "ns3/gnuplot.h"
48 #include "ns3/command-line.h"
49 #include "ns3/yans-wifi-helper.h"
50 #include "ns3/ssid.h"
51 #include "ns3/propagation-loss-model.h"
52 #include "ns3/propagation-delay-model.h"
53 #include "ns3/rng-seed-manager.h"
54 #include "ns3/mobility-helper.h"
55 #include "ns3/wifi-net-device.h"
56 #include "ns3/packet-socket-helper.h"
57 #include "ns3/packet-socket-client.h"
58 #include "ns3/packet-socket-server.h"
59 #include "ns3/ht-configuration.h"
60 #include "ns3/he-configuration.h"
61 
62 using namespace ns3;
63 
64 NS_LOG_COMPONENT_DEFINE ("WifiManagerExample");
65 
66 // 290K @ 20 MHz
67 const double NOISE_DBM_Hz = -174.0;
69 
70 double g_intervalBytes = 0;
71 uint64_t g_intervalRate = 0;
72 
73 void
75 {
76  g_intervalBytes += pkt->GetSize ();
77 }
78 
79 void
80 RateChange (uint64_t oldVal, uint64_t newVal)
81 {
82  NS_LOG_DEBUG ("Change from " << oldVal << " to " << newVal);
83  g_intervalRate = newVal;
84 }
85 
87 struct Step
88 {
89  double stepSize;
90  double stepTime;
91 };
92 
95 {
97  {
98  m_name = "none";
99  }
113  StandardInfo (std::string name, WifiStandard standard, WifiPhyBand band, uint16_t width, double snrLow, double snrHigh, double xMin, double xMax, double yMax)
114  : m_name (name),
115  m_standard (standard),
116  m_band (band),
117  m_width (width),
118  m_snrLow (snrLow),
119  m_snrHigh (snrHigh),
120  m_xMin (xMin),
121  m_xMax (xMax),
122  m_yMax (yMax)
123  {
124  }
125  std::string m_name;
128  uint16_t m_width;
129  double m_snrLow;
130  double m_snrHigh;
131  double m_xMin;
132  double m_xMax;
133  double m_yMax;
134 };
135 
136 void
137 ChangeSignalAndReportRate (Ptr<FixedRssLossModel> rssModel, Step step, double rss, Gnuplot2dDataset& rateDataset, Gnuplot2dDataset& actualDataset)
138 {
139  NS_LOG_FUNCTION (rssModel << step.stepSize << step.stepTime << rss);
140  double snr = rss - noiseDbm;
141  rateDataset.Add (snr, g_intervalRate / 1e6);
142  // Calculate received rate since last interval
143  double currentRate = ((g_intervalBytes * 8) / step.stepTime) / 1e6; // Mb/s
144  actualDataset.Add (snr, currentRate);
145  rssModel->SetRss (rss - step.stepSize);
146  NS_LOG_INFO ("At time " << Simulator::Now ().As (Time::S) << "; selected rate " << (g_intervalRate / 1e6) << "; observed rate " << currentRate << "; setting new power to " << rss - step.stepSize);
147  g_intervalBytes = 0;
148  Simulator::Schedule (Seconds (step.stepTime), &ChangeSignalAndReportRate, rssModel, step, (rss - step.stepSize), rateDataset, actualDataset);
149 }
150 
151 int main (int argc, char *argv[])
152 {
153  std::vector <StandardInfo> serverStandards;
154  std::vector <StandardInfo> clientStandards;
155  uint32_t steps;
156  uint32_t rtsThreshold = 999999; // disabled even for large A-MPDU
157  uint32_t maxAmpduSize = 65535;
158  double stepSize = 1; // dBm
159  double stepTime = 1; // seconds
160  uint32_t packetSize = 1024; // bytes
161  bool broadcast = 0;
162  int ap1_x = 0;
163  int ap1_y = 0;
164  int sta1_x = 5;
165  int sta1_y = 0;
166  uint16_t serverNss = 1;
167  uint16_t clientNss = 1;
168  uint16_t serverShortGuardInterval = 800;
169  uint16_t clientShortGuardInterval = 800;
170  uint16_t serverChannelWidth = 0; // use default for standard and band
171  uint16_t clientChannelWidth = 0; // use default for standard and band
172  std::string wifiManager ("Ideal");
173  std::string standard ("802.11a");
174  StandardInfo serverSelectedStandard;
175  StandardInfo clientSelectedStandard;
176  bool infrastructure = false;
177  uint32_t maxSlrc = 7;
178  uint32_t maxSsrc = 7;
179 
180  CommandLine cmd (__FILE__);
181  cmd.AddValue ("maxSsrc", "The maximum number of retransmission attempts for a RTS packet", maxSsrc);
182  cmd.AddValue ("maxSlrc", "The maximum number of retransmission attempts for a Data packet", maxSlrc);
183  cmd.AddValue ("rtsThreshold", "RTS threshold", rtsThreshold);
184  cmd.AddValue ("maxAmpduSize", "Max A-MPDU size", maxAmpduSize);
185  cmd.AddValue ("stepSize", "Power between steps (dBm)", stepSize);
186  cmd.AddValue ("stepTime", "Time on each step (seconds)", stepTime);
187  cmd.AddValue ("broadcast", "Send broadcast instead of unicast", broadcast);
188  cmd.AddValue ("serverChannelWidth", "Set channel width of the server (valid only for 802.11n or ac)", serverChannelWidth);
189  cmd.AddValue ("clientChannelWidth", "Set channel width of the client (valid only for 802.11n or ac)", clientChannelWidth);
190  cmd.AddValue ("serverNss", "Set nss of the server (valid only for 802.11n or ac)", serverNss);
191  cmd.AddValue ("clientNss", "Set nss of the client (valid only for 802.11n or ac)", clientNss);
192  cmd.AddValue ("serverShortGuardInterval", "Set short guard interval of the server (802.11n/ac/ax) in nanoseconds", serverShortGuardInterval);
193  cmd.AddValue ("clientShortGuardInterval", "Set short guard interval of the client (802.11n/ac/ax) in nanoseconds", clientShortGuardInterval);
194  cmd.AddValue ("standard", "Set standard (802.11a, 802.11b, 802.11g, 802.11p-10MHz, 802.11p-5MHz, 802.11n-5GHz, 802.11n-2.4GHz, 802.11ac, 802.11ax-6GHz, 802.11ax-5GHz, 802.11ax-2.4GHz)", standard);
195  cmd.AddValue ("wifiManager", "Set wifi rate manager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, MinstrelHt, Onoe, Rraa, ThompsonSampling)", wifiManager);
196  cmd.AddValue ("infrastructure", "Use infrastructure instead of adhoc", infrastructure);
197  cmd.Parse (argc,argv);
198 
199  // Print out some explanation of what this program does
200  std::cout << std::endl << "This program demonstrates and plots the operation of different " << std::endl;
201  std::cout << "Wi-Fi rate controls on different station configurations," << std::endl;
202  std::cout << "by stepping down the received signal strength across a wide range" << std::endl;
203  std::cout << "and observing the adjustment of the rate." << std::endl;
204  std::cout << "Run 'wifi-manager-example --PrintHelp' to show program options." << std::endl << std::endl;
205 
206  if (infrastructure == false)
207  {
208  NS_ABORT_MSG_IF (serverNss != clientNss, "In ad hoc mode, we assume sender and receiver are similarly configured");
209  }
210 
211  if (standard == "802.11b")
212  {
213  if (serverChannelWidth == 0)
214  {
216  }
217  NS_ABORT_MSG_IF (serverChannelWidth != 22 && serverChannelWidth != 22, "Invalid channel width for standard " << standard);
218  NS_ABORT_MSG_IF (serverNss != 1, "Invalid nss for standard " << standard);
219  if (clientChannelWidth == 0)
220  {
222  }
223  NS_ABORT_MSG_IF (clientChannelWidth != 22 && clientChannelWidth != 22, "Invalid channel width for standard " << standard);
224  NS_ABORT_MSG_IF (clientNss != 1, "Invalid nss for standard " << standard);
225  }
226  else if (standard == "802.11a" || standard == "802.11g")
227  {
228  if (serverChannelWidth == 0)
229  {
231  }
232  NS_ABORT_MSG_IF (serverChannelWidth != 20, "Invalid channel width for standard " << standard);
233  NS_ABORT_MSG_IF (serverNss != 1, "Invalid nss for standard " << standard);
234  if (clientChannelWidth == 0)
235  {
237  }
238  NS_ABORT_MSG_IF (clientChannelWidth != 20, "Invalid channel width for standard " << standard);
239  NS_ABORT_MSG_IF (clientNss != 1, "Invalid nss for standard " << standard);
240  }
241  else if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz")
242  {
243  WifiPhyBand band = (standard == "802.11n-2.4GHz" ? WIFI_PHY_BAND_2_4GHZ : WIFI_PHY_BAND_5GHZ);
244  if (serverChannelWidth == 0)
245  {
246  serverChannelWidth = GetDefaultChannelWidth (WIFI_STANDARD_80211n, band);
247  }
248  NS_ABORT_MSG_IF (serverChannelWidth != 20 && serverChannelWidth != 40, "Invalid channel width for standard " << standard);
249  NS_ABORT_MSG_IF (serverNss == 0 || serverNss > 4, "Invalid nss " << serverNss << " for standard " << standard);
250  if (clientChannelWidth == 0)
251  {
252  clientChannelWidth = GetDefaultChannelWidth (WIFI_STANDARD_80211n, band);
253  }
254  NS_ABORT_MSG_IF (clientChannelWidth != 20 && clientChannelWidth != 40, "Invalid channel width for standard " << standard);
255  NS_ABORT_MSG_IF (clientNss == 0 || clientNss > 4, "Invalid nss " << clientNss << " for standard " << standard);
256  }
257  else if (standard == "802.11ac")
258  {
259  if (serverChannelWidth == 0)
260  {
262  }
263  NS_ABORT_MSG_IF (serverChannelWidth != 20 && serverChannelWidth != 40 && serverChannelWidth != 80 && serverChannelWidth != 160, "Invalid channel width for standard " << standard);
264  NS_ABORT_MSG_IF (serverNss == 0 || serverNss > 4, "Invalid nss " << serverNss << " for standard " << standard);
265  if (clientChannelWidth == 0)
266  {
268  }
269  NS_ABORT_MSG_IF (clientChannelWidth != 20 && clientChannelWidth != 40 && clientChannelWidth != 80 && clientChannelWidth != 160, "Invalid channel width for standard " << standard);
270  NS_ABORT_MSG_IF (clientNss == 0 || clientNss > 4, "Invalid nss " << clientNss << " for standard " << standard);
271  }
272  else if (standard == "802.11ax-6GHz" ||standard == "802.11ax-5GHz" || standard == "802.11ax-2.4GHz")
273  {
274  WifiPhyBand band = (standard == "802.11ax-2.4GHz" ? WIFI_PHY_BAND_2_4GHZ : standard == "802.11ax-6GHz" ? WIFI_PHY_BAND_6GHZ : WIFI_PHY_BAND_5GHZ);
275  if (serverChannelWidth == 0)
276  {
277  serverChannelWidth = GetDefaultChannelWidth (WIFI_STANDARD_80211ax, band);
278  }
279  NS_ABORT_MSG_IF (serverChannelWidth != 20 && serverChannelWidth != 40 && serverChannelWidth != 80 && serverChannelWidth != 160, "Invalid channel width for standard " << standard);
280  NS_ABORT_MSG_IF (serverNss == 0 || serverNss > 4, "Invalid nss " << serverNss << " for standard " << standard);
281  if (clientChannelWidth == 0)
282  {
283  clientChannelWidth = GetDefaultChannelWidth (WIFI_STANDARD_80211ax, band);
284  }
285  NS_ABORT_MSG_IF (clientChannelWidth != 20 && clientChannelWidth != 40 && clientChannelWidth != 80 && clientChannelWidth != 160, "Invalid channel width for standard " << standard);
286  NS_ABORT_MSG_IF (clientNss == 0 || clientNss > 4, "Invalid nss " << clientNss << " for standard " << standard);
287  }
288 
289  // As channel width increases, scale up plot's yRange value
290  uint32_t channelRateFactor = std::max (clientChannelWidth, serverChannelWidth) / 20;
291  channelRateFactor = channelRateFactor * std::max (clientNss, serverNss);
292 
293  // The first number is channel width, second is minimum SNR, third is maximum
294  // SNR, fourth and fifth provide xrange axis limits, and sixth the yaxis
295  // maximum
296  serverStandards.push_back (StandardInfo ("802.11a", WIFI_STANDARD_80211a, WIFI_PHY_BAND_5GHZ, 20, 3, 27, 0, 30, 60));
297  serverStandards.push_back (StandardInfo ("802.11b", WIFI_STANDARD_80211b, WIFI_PHY_BAND_2_4GHZ, 22, -5, 11, -6, 15, 15));
298  serverStandards.push_back (StandardInfo ("802.11g", WIFI_STANDARD_80211g, WIFI_PHY_BAND_2_4GHZ, 20, -5, 27, -6, 30, 60));
299  serverStandards.push_back (StandardInfo ("802.11n-5GHz", WIFI_STANDARD_80211n, WIFI_PHY_BAND_5GHZ, serverChannelWidth, 3, 30, 0, 35, 80 * channelRateFactor));
300  serverStandards.push_back (StandardInfo ("802.11n-2.4GHz", WIFI_STANDARD_80211n, WIFI_PHY_BAND_2_4GHZ, serverChannelWidth, 3, 30, 0, 35, 80 * channelRateFactor));
301  serverStandards.push_back (StandardInfo ("802.11ac", WIFI_STANDARD_80211ac, WIFI_PHY_BAND_5GHZ, serverChannelWidth, 5, 50, 0, 55, 120 * channelRateFactor));
302  serverStandards.push_back (StandardInfo ("802.11p-10MHz", WIFI_STANDARD_80211p, WIFI_PHY_BAND_5GHZ, 10, 3, 27, 0, 30, 60));
303  serverStandards.push_back (StandardInfo ("802.11p-5MHz", WIFI_STANDARD_80211p, WIFI_PHY_BAND_5GHZ, 5, 3, 27, 0, 30, 60));
304  serverStandards.push_back (StandardInfo ("802.11ax-6GHz", WIFI_STANDARD_80211ax, WIFI_PHY_BAND_6GHZ, serverChannelWidth, 5, 55, 0, 60, 120 * channelRateFactor));
305  serverStandards.push_back (StandardInfo ("802.11ax-5GHz", WIFI_STANDARD_80211ax, WIFI_PHY_BAND_5GHZ, serverChannelWidth, 5, 55, 0, 60, 120 * channelRateFactor));
306  serverStandards.push_back (StandardInfo ("802.11ax-2.4GHz", WIFI_STANDARD_80211ax, WIFI_PHY_BAND_2_4GHZ, serverChannelWidth, 5, 55, 0, 60, 120 * channelRateFactor));
307 
308  clientStandards.push_back (StandardInfo ("802.11a", WIFI_STANDARD_80211a, WIFI_PHY_BAND_5GHZ, 20, 3, 27, 0, 30, 60));
309  clientStandards.push_back (StandardInfo ("802.11b", WIFI_STANDARD_80211b, WIFI_PHY_BAND_2_4GHZ, 22, -5, 11, -6, 15, 15));
310  clientStandards.push_back (StandardInfo ("802.11g", WIFI_STANDARD_80211g, WIFI_PHY_BAND_2_4GHZ, 20, -5, 27, -6, 30, 60));
311  clientStandards.push_back (StandardInfo ("802.11n-5GHz", WIFI_STANDARD_80211n, WIFI_PHY_BAND_5GHZ, clientChannelWidth, 3, 30, 0, 35, 80 * channelRateFactor));
312  clientStandards.push_back (StandardInfo ("802.11n-2.4GHz", WIFI_STANDARD_80211n, WIFI_PHY_BAND_2_4GHZ, clientChannelWidth, 3, 30, 0, 35, 80 * channelRateFactor));
313  clientStandards.push_back (StandardInfo ("802.11ac", WIFI_STANDARD_80211ac, WIFI_PHY_BAND_5GHZ, clientChannelWidth, 5, 50, 0, 55, 120 * channelRateFactor));
314  clientStandards.push_back (StandardInfo ("802.11p-10MHz", WIFI_STANDARD_80211p, WIFI_PHY_BAND_5GHZ, 10, 3, 27, 0, 30, 60));
315  clientStandards.push_back (StandardInfo ("802.11p-5MHz", WIFI_STANDARD_80211p, WIFI_PHY_BAND_5GHZ, 5, 3, 27, 0, 30, 60));
316  clientStandards.push_back (StandardInfo ("802.11ax-6GHz", WIFI_STANDARD_80211ax, WIFI_PHY_BAND_6GHZ, clientChannelWidth, 5, 55, 0, 60, 160 * channelRateFactor));
317  clientStandards.push_back (StandardInfo ("802.11ax-5GHz", WIFI_STANDARD_80211ax, WIFI_PHY_BAND_5GHZ, clientChannelWidth, 5, 55, 0, 60, 160 * channelRateFactor));
318  clientStandards.push_back (StandardInfo ("802.11ax-2.4GHz", WIFI_STANDARD_80211ax, WIFI_PHY_BAND_2_4GHZ, clientChannelWidth, 5, 55, 0, 60, 160 * channelRateFactor));
319 
320  for (std::vector<StandardInfo>::size_type i = 0; i != serverStandards.size (); i++)
321  {
322  if (standard == serverStandards[i].m_name)
323  {
324  serverSelectedStandard = serverStandards[i];
325  }
326  }
327  for (std::vector<StandardInfo>::size_type i = 0; i != clientStandards.size (); i++)
328  {
329  if (standard == clientStandards[i].m_name)
330  {
331  clientSelectedStandard = clientStandards[i];
332  }
333  }
334 
335  NS_ABORT_MSG_IF (serverSelectedStandard.m_name == "none", "Standard " << standard << " not found");
336  NS_ABORT_MSG_IF (clientSelectedStandard.m_name == "none", "Standard " << standard << " not found");
337  std::cout << "Testing " << serverSelectedStandard.m_name << " with " << wifiManager << " ..." << std::endl;
338  NS_ABORT_MSG_IF (clientSelectedStandard.m_snrLow >= clientSelectedStandard.m_snrHigh, "SNR values in wrong order");
339  steps = static_cast<uint32_t> (std::abs (static_cast<double> (clientSelectedStandard.m_snrHigh - clientSelectedStandard.m_snrLow ) / stepSize) + 1);
340  NS_LOG_DEBUG ("Using " << steps << " steps for SNR range " << clientSelectedStandard.m_snrLow << ":" << clientSelectedStandard.m_snrHigh);
341  Ptr<Node> clientNode = CreateObject<Node> ();
342  Ptr<Node> serverNode = CreateObject<Node> ();
343 
344  std::string plotName = "wifi-manager-example-";
345  std::string dataName = "wifi-manager-example-";
346  plotName += wifiManager;
347  dataName += wifiManager;
348  plotName += "-";
349  dataName += "-";
350  plotName += standard;
351  dataName += standard;
352  if (standard == "802.11n-5GHz"
353  || standard == "802.11n-2.4GHz"
354  || standard == "802.11ac"
355  || standard == "802.11ax-6GHz"
356  || standard == "802.11ax-5GHz"
357  || standard == "802.11ax-2.4GHz")
358  {
359  plotName += "-server_";
360  dataName += "-server_";
361  std::ostringstream oss;
362  oss << serverChannelWidth << "MHz_" << serverShortGuardInterval << "ns_" << serverNss << "SS";
363  plotName += oss.str ();
364  dataName += oss.str ();
365  plotName += "-client_";
366  dataName += "-client_";
367  oss.str ("");
368  oss << clientChannelWidth << "MHz_" << clientShortGuardInterval << "ns_" << clientNss << "SS";
369  plotName += oss.str ();
370  dataName += oss.str ();
371  }
372  plotName += ".eps";
373  dataName += ".plt";
374  std::ofstream outfile (dataName.c_str ());
375  Gnuplot gnuplot = Gnuplot (plotName);
376 
377  Config::SetDefault ("ns3::WifiRemoteStationManager::MaxSlrc", UintegerValue (maxSlrc));
378  Config::SetDefault ("ns3::WifiRemoteStationManager::MaxSsrc", UintegerValue (maxSsrc));
379  Config::SetDefault ("ns3::MinstrelWifiManager::PrintStats", BooleanValue (true));
380  Config::SetDefault ("ns3::MinstrelWifiManager::PrintSamples", BooleanValue (true));
381  Config::SetDefault ("ns3::MinstrelHtWifiManager::PrintStats", BooleanValue (true));
382 
384  wifi.SetStandard (serverSelectedStandard.m_standard);
385  YansWifiPhyHelper wifiPhy;
386 
387  Ptr<YansWifiChannel> wifiChannel = CreateObject<YansWifiChannel> ();
388  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
389  wifiChannel->SetPropagationDelayModel (delayModel);
390  Ptr<FixedRssLossModel> rssLossModel = CreateObject<FixedRssLossModel> ();
391  wifiChannel->SetPropagationLossModel (rssLossModel);
392  wifiPhy.SetChannel (wifiChannel);
393 
394  wifi.SetRemoteStationManager ("ns3::" + wifiManager + "WifiManager", "RtsCtsThreshold", UintegerValue (rtsThreshold));
395 
396  NetDeviceContainer serverDevice;
397  NetDeviceContainer clientDevice;
398 
400 
401  WifiMacHelper wifiMac;
402  if (infrastructure)
403  {
404  Ssid ssid = Ssid ("ns-3-ssid");
405  wifiMac.SetType ("ns3::StaWifiMac",
406  "Ssid", SsidValue (ssid));
407  channelValue.Set (WifiPhy::ChannelTuple {0, serverSelectedStandard.m_width,
408  serverSelectedStandard.m_band, 0});
409  wifiPhy.Set ("ChannelSettings", channelValue);
410  serverDevice = wifi.Install (wifiPhy, wifiMac, serverNode);
411 
412  wifiMac.SetType ("ns3::ApWifiMac",
413  "Ssid", SsidValue (ssid));
414  channelValue.Set (WifiPhy::ChannelTuple {0, clientSelectedStandard.m_width,
415  clientSelectedStandard.m_band, 0});
416  clientDevice = wifi.Install (wifiPhy, wifiMac, clientNode);
417  }
418  else
419  {
420  wifiMac.SetType ("ns3::AdhocWifiMac");
421  channelValue.Set (WifiPhy::ChannelTuple {0, serverSelectedStandard.m_width,
422  serverSelectedStandard.m_band, 0});
423  wifiPhy.Set ("ChannelSettings", channelValue);
424  serverDevice = wifi.Install (wifiPhy, wifiMac, serverNode);
425 
426  channelValue.Set (WifiPhy::ChannelTuple {0, clientSelectedStandard.m_width,
427  clientSelectedStandard.m_band, 0});
428  clientDevice = wifi.Install (wifiPhy, wifiMac, clientNode);
429  }
430 
433  wifi.AssignStreams (serverDevice, 100);
434  wifi.AssignStreams (clientDevice, 100);
435 
436  Config::Set ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize", UintegerValue (maxAmpduSize));
437 
438  Config::ConnectWithoutContext ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager + "WifiManager/Rate", MakeCallback (&RateChange));
439 
440  // Configure the mobility.
442  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
443  //Initial position of AP and STA
444  positionAlloc->Add (Vector (ap1_x, ap1_y, 0.0));
445  NS_LOG_INFO ("Setting initial AP position to " << Vector (ap1_x, ap1_y, 0.0));
446  positionAlloc->Add (Vector (sta1_x, sta1_y, 0.0));
447  NS_LOG_INFO ("Setting initial STA position to " << Vector (sta1_x, sta1_y, 0.0));
448  mobility.SetPositionAllocator (positionAlloc);
449  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
450  mobility.Install (clientNode);
451  mobility.Install (serverNode);
452 
453  Gnuplot2dDataset rateDataset (clientSelectedStandard.m_name + std::string ("-rate selected"));
454  Gnuplot2dDataset actualDataset (clientSelectedStandard.m_name + std::string ("-observed"));
455  Step step;
456  step.stepSize = stepSize;
457  step.stepTime = stepTime;
458 
459  // Perform post-install configuration from defaults for channel width,
460  // guard interval, and nss, if necessary
461  // Obtain pointer to the WifiPhy
462  Ptr<NetDevice> ndClient = clientDevice.Get (0);
463  Ptr<NetDevice> ndServer = serverDevice.Get (0);
464  Ptr<WifiNetDevice> wndClient = ndClient->GetObject<WifiNetDevice> ();
465  Ptr<WifiNetDevice> wndServer = ndServer->GetObject<WifiNetDevice> ();
466  Ptr<WifiPhy> wifiPhyPtrClient = wndClient->GetPhy ();
467  Ptr<WifiPhy> wifiPhyPtrServer = wndServer->GetPhy ();
468  uint8_t t_clientNss = static_cast<uint8_t> (clientNss);
469  uint8_t t_serverNss = static_cast<uint8_t> (serverNss);
470  wifiPhyPtrClient->SetNumberOfAntennas (t_clientNss);
471  wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams (t_clientNss);
472  wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams (t_clientNss);
473  wifiPhyPtrServer->SetNumberOfAntennas (t_serverNss);
474  wifiPhyPtrServer->SetMaxSupportedTxSpatialStreams (t_serverNss);
475  wifiPhyPtrServer->SetMaxSupportedRxSpatialStreams (t_serverNss);
476  // Only set the guard interval for HT and VHT modes
477  if (serverSelectedStandard.m_name == "802.11n-5GHz"
478  || serverSelectedStandard.m_name == "802.11n-2.4GHz"
479  || serverSelectedStandard.m_name == "802.11ac")
480  {
481  Ptr<HtConfiguration> clientHtConfiguration = wndClient->GetHtConfiguration ();
482  clientHtConfiguration->SetShortGuardIntervalSupported (clientShortGuardInterval == 400);
483  Ptr<HtConfiguration> serverHtConfiguration = wndServer->GetHtConfiguration ();
484  serverHtConfiguration->SetShortGuardIntervalSupported (serverShortGuardInterval == 400);
485  }
486  else if (serverSelectedStandard.m_name == "802.11ax-6GHz"
487  || serverSelectedStandard.m_name == "802.11ax-5GHz"
488  || serverSelectedStandard.m_name == "802.11ax-2.4GHz")
489  {
490  wndServer->GetHeConfiguration ()->SetGuardInterval (NanoSeconds (serverShortGuardInterval));
491  wndClient->GetHeConfiguration ()->SetGuardInterval (NanoSeconds (clientShortGuardInterval));
492  }
493  NS_LOG_DEBUG ("Channel width " << wifiPhyPtrClient->GetChannelWidth () << " noiseDbm " << noiseDbm);
494  NS_LOG_DEBUG ("NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams ());
495 
496  // Configure signal and noise, and schedule first iteration
497  noiseDbm += 10 * log10 (clientSelectedStandard.m_width * 1000000);
498  double rssCurrent = (clientSelectedStandard.m_snrHigh + noiseDbm);
499  rssLossModel->SetRss (rssCurrent);
500  NS_LOG_INFO ("Setting initial Rss to " << rssCurrent);
501  //Move the STA by stepsSize meters every stepTime seconds
502  Simulator::Schedule (Seconds (0.5 + stepTime), &ChangeSignalAndReportRate, rssLossModel, step, rssCurrent, rateDataset, actualDataset);
503 
504  PacketSocketHelper packetSocketHelper;
505  packetSocketHelper.Install (serverNode);
506  packetSocketHelper.Install (clientNode);
507 
508  PacketSocketAddress socketAddr;
509  socketAddr.SetSingleDevice (serverDevice.Get (0)->GetIfIndex ());
510  if (broadcast)
511  {
512  socketAddr.SetPhysicalAddress (serverDevice.Get (0)->GetBroadcast ());
513  }
514  else
515  {
516  socketAddr.SetPhysicalAddress (serverDevice.Get (0)->GetAddress ());
517  }
518  // Arbitrary protocol type.
519  // Note: PacketSocket doesn't have any L4 multiplexing or demultiplexing
520  // The only mux/demux is based on the protocol field
521  socketAddr.SetProtocol (1);
522 
523  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient> ();
524  client->SetRemote (socketAddr);
525  client->SetStartTime (Seconds (0.5)); // allow simulation warmup
526  client->SetAttribute ("MaxPackets", UintegerValue (0)); // unlimited
527  client->SetAttribute ("PacketSize", UintegerValue (packetSize));
528 
529  // Set a maximum rate 10% above the yMax specified for the selected standard
530  double rate = clientSelectedStandard.m_yMax * 1e6 * 1.10;
531  double clientInterval = static_cast<double> (packetSize) * 8 / rate;
532  NS_LOG_DEBUG ("Setting interval to " << clientInterval << " sec for rate of " << rate << " bits/sec");
533 
534  client->SetAttribute ("Interval", TimeValue (Seconds (clientInterval)));
535  clientNode->AddApplication (client);
536 
537  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
538  server->SetLocal (socketAddr);
539  server->TraceConnectWithoutContext ("Rx", MakeCallback (&PacketRx));
540  serverNode->AddApplication (server);
541 
542  Simulator::Stop (Seconds ((steps + 1) * stepTime));
543  Simulator::Run ();
545 
546  gnuplot.AddDataset (rateDataset);
547  gnuplot.AddDataset (actualDataset);
548 
549  std::ostringstream xMinStr, xMaxStr, yMaxStr;
550  std::string xRangeStr ("set xrange [");
551  xMinStr << clientSelectedStandard.m_xMin;
552  xRangeStr.append (xMinStr.str ());
553  xRangeStr.append (":");
554  xMaxStr << clientSelectedStandard.m_xMax;
555  xRangeStr.append (xMaxStr.str ());
556  xRangeStr.append ("]");
557  std::string yRangeStr ("set yrange [0:");
558  yMaxStr << clientSelectedStandard.m_yMax;
559  yRangeStr.append (yMaxStr.str ());
560  yRangeStr.append ("]");
561 
562  std::string title ("Results for ");
563  title.append (standard);
564  title.append (" with ");
565  title.append (wifiManager);
566  title.append ("\\n");
567  if (standard == "802.11n-5GHz"
568  || standard == "802.11n-2.4GHz"
569  || standard == "802.11ac"
570  || standard == "802.11ax-6GHz"
571  || standard == "802.11ax-5GHz"
572  || standard == "802.11ax-2.4GHz")
573  {
574  std::ostringstream serverGiStrStr;
575  std::ostringstream serverWidthStrStr;
576  std::ostringstream serverNssStrStr;
577  title.append ("server: width=");
578  serverWidthStrStr << serverSelectedStandard.m_width;
579  title.append (serverWidthStrStr.str ());
580  title.append ("MHz");
581  title.append (" GI=");
582  serverGiStrStr << serverShortGuardInterval;
583  title.append (serverGiStrStr.str ());
584  title.append ("ns");
585  title.append (" nss=");
586  serverNssStrStr << serverNss;
587  title.append (serverNssStrStr.str ());
588  title.append ("\\n");
589  std::ostringstream clientGiStrStr;
590  std::ostringstream clientWidthStrStr;
591  std::ostringstream clientNssStrStr;
592  title.append ("client: width=");
593  clientWidthStrStr << clientSelectedStandard.m_width;
594  title.append (clientWidthStrStr.str ());
595  title.append ("MHz");
596  title.append (" GI=");
597  clientGiStrStr << clientShortGuardInterval;
598  title.append (clientGiStrStr.str ());
599  title.append ("ns");
600  title.append (" nss=");
601  clientNssStrStr << clientNss;
602  title.append (clientNssStrStr.str ());
603  }
604  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
605  gnuplot.SetLegend ("SNR (dB)", "Rate (Mb/s)");
606  gnuplot.SetTitle (title);
607  gnuplot.SetExtra (xRangeStr);
608  gnuplot.AppendExtra (yRangeStr);
609  gnuplot.AppendExtra ("set key top left");
610  gnuplot.GenerateOutput (outfile);
611  outfile.close ();
612 
613  return 0;
614 }
615 
#define max(a, b)
Definition: 80211b.c:43
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Parse command-line arguments.
Definition: command-line.h:229
Class to represent a 2D points plot.
Definition: gnuplot.h:118
void Add(double x, double y)
Definition: gnuplot.cc:363
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:760
void SetLegend(const std::string &xLegend, const std::string &yLegend)
Definition: gnuplot.cc:740
void SetTerminal(const std::string &terminal)
Definition: gnuplot.cc:728
void AppendExtra(const std::string &extra)
Definition: gnuplot.cc:753
void GenerateOutput(std::ostream &os)
Writes gnuplot commands and data values to a single output stream.
Definition: gnuplot.cc:766
void SetExtra(const std::string &extra)
Definition: gnuplot.cc:747
void SetTitle(const std::string &title)
Definition: gnuplot.cc:734
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
virtual Address GetBroadcast(void) const =0
virtual Address GetAddress(void) const =0
virtual uint32_t GetIfIndex(void) const =0
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:159
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
Definition: ssid.h:105
@ S
second
Definition: nstime.h:114
AttributeValue implementation for Time.
Definition: nstime.h:1308
Hold objects of type std::tuple<Args...>.
Definition: tuple.h:70
void Set(const result_type &value)
Set the stored values.
Definition: tuple.h:325
Hold an unsigned integer type.
Definition: uinteger.h:44
helps to create WifiNetDevice objects
Definition: wifi-helper.h:274
create MAC layers for a ns3::WifiNetDevice.
void SetType(std::string type, Args &&... args)
Hold together all Wifi-related objects.
Ptr< HtConfiguration > GetHtConfiguration(void) const
Ptr< WifiPhy > GetPhy(void) const
Ptr< HeConfiguration > GetHeConfiguration(void) const
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:154
void SetNumberOfAntennas(uint8_t antennas)
Definition: wifi-phy.cc:1077
void SetMaxSupportedRxSpatialStreams(uint8_t streams)
Definition: wifi-phy.cc:1126
void SetMaxSupportedTxSpatialStreams(uint8_t streams)
Definition: wifi-phy.cc:1095
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:833
Make it easy to create and manage PHY objects for the YANS model.
void SetChannel(Ptr< YansWifiChannel > channel)
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:901
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:839
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1268
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211p
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211g
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ WIFI_STANDARD_80211b
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
Definition: wifi-phy-band.h:39
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint16_t GetDefaultChannelWidth(WifiStandard standard, WifiPhyBand band)
Get the default channel width for the given PHY standard and band.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
cmd
Definition: second.py:35
ssid
Definition: third.py:100
wifi
Definition: third.py:96
mobility
Definition: third.py:108
StandardInfo structure.
std::string m_name
name
StandardInfo(std::string name, WifiStandard standard, WifiPhyBand band, uint16_t width, double snrLow, double snrHigh, double xMin, double xMax, double yMax)
Constructor.
uint16_t m_width
channel width
double m_yMax
Y maximum.
WifiStandard m_standard
standard
WifiPhyBand m_band
PHY band.
double m_snrHigh
highest SNR
double m_xMax
X maximum.
double m_xMin
X minimum.
double m_snrLow
lowest SNR
Step structure.
double stepSize
step size in dBm
double stepTime
step size in seconds
uint64_t g_intervalRate
void RateChange(uint64_t oldVal, uint64_t newVal)
const double NOISE_DBM_Hz
void PacketRx(Ptr< const Packet > pkt, const Address &addr)
double g_intervalBytes
double noiseDbm
void ChangeSignalAndReportRate(Ptr< FixedRssLossModel > rssModel, Step step, double rss, Gnuplot2dDataset &rateDataset, Gnuplot2dDataset &actualDataset)
static const uint32_t packetSize