A Discrete-Event Network Simulator
API
wifi-manager-example.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 University of Washington
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  * Authors: Tom Henderson <tomhend@u.washington.edu>
18  * Matías Richart <mrichart@fing.edu.uy>
19  * Sébastien Deronne <sebastien.deronne@gmail.com>
20  */
21 
22 // Test the operation of a wifi manager as the SNR is varied, and create
23 // a gnuplot output file for plotting.
24 //
25 // The test consists of a device acting as server and a device as client generating traffic.
26 //
27 // The output consists of a plot of the rate observed and selected at the client device.
28 // A special FixedRss propagation loss model is used to set a specific receive
29 // power on the receiver. The noise power is exclusively the thermal noise
30 // for the channel bandwidth (no noise figure is configured). Furthermore,
31 // the CCA sensitivity attribute in WifiPhy can prevent signals from being
32 // received even though the error model would permit it. Therefore, for
33 // the purpose of this example, the CCA sensitivity is lowered to a value
34 // that disables it, and furthermore, the preamble detection model (which
35 // also contains a similar threshold) is disabled.
36 //
37 // By default, the 802.11a standard using IdealWifiManager is plotted. Several command line
38 // arguments can change the following options:
39 // --wifiManager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, MinstrelHt, Onoe, Rraa,
40 // ThompsonSampling)
41 // --standard (802.11a, 802.11b, 802.11g, 802.11p-10MHz, 802.11p-5MHz, 802.11n-5GHz, 802.11n-2.4GHz,
42 // 802.11ac, 802.11ax-6GHz, 802.11ax-5GHz, 802.11ax-2.4GHz)
43 // --serverShortGuardInterval and --clientShortGuardInterval (for 802.11n/ac)
44 // --serverNss and --clientNss (for 802.11n/ac)
45 // --serverChannelWidth and --clientChannelWidth (for 802.11n/ac)
46 // --broadcast instead of unicast (default is unicast)
47 // --rtsThreshold (by default, value of 99999 disables it)
48 
49 #include "ns3/boolean.h"
50 #include "ns3/command-line.h"
51 #include "ns3/config.h"
52 #include "ns3/double.h"
53 #include "ns3/enum.h"
54 #include "ns3/gnuplot.h"
55 #include "ns3/he-configuration.h"
56 #include "ns3/ht-configuration.h"
57 #include "ns3/log.h"
58 #include "ns3/mobility-helper.h"
59 #include "ns3/packet-socket-client.h"
60 #include "ns3/packet-socket-helper.h"
61 #include "ns3/packet-socket-server.h"
62 #include "ns3/propagation-delay-model.h"
63 #include "ns3/propagation-loss-model.h"
64 #include "ns3/rng-seed-manager.h"
65 #include "ns3/ssid.h"
66 #include "ns3/tuple.h"
67 #include "ns3/uinteger.h"
68 #include "ns3/wifi-net-device.h"
69 #include "ns3/yans-wifi-helper.h"
70 
71 using namespace ns3;
72 
73 NS_LOG_COMPONENT_DEFINE("WifiManagerExample");
74 
75 // 290K @ 20 MHz
76 const double NOISE_DBM_Hz = -174.0;
78 
79 double g_intervalBytes = 0;
80 uint64_t g_intervalRate = 0;
81 
88 void
90 {
91  g_intervalBytes += pkt->GetSize();
92 }
93 
100 void
101 RateChange(uint64_t oldVal, uint64_t newVal)
102 {
103  NS_LOG_DEBUG("Change from " << oldVal << " to " << newVal);
104  g_intervalRate = newVal;
105 }
106 
108 struct Step
109 {
110  double stepSize;
111  double stepTime;
112 };
113 
116 {
118  {
119  m_name = "none";
120  }
121 
135  StandardInfo(std::string name,
136  WifiStandard standard,
137  WifiPhyBand band,
138  uint16_t width,
139  double snrLow,
140  double snrHigh,
141  double xMin,
142  double xMax,
143  double yMax)
144  : m_name(name),
145  m_standard(standard),
146  m_band(band),
147  m_width(width),
148  m_snrLow(snrLow),
149  m_snrHigh(snrHigh),
150  m_xMin(xMin),
151  m_xMax(xMax),
152  m_yMax(yMax)
153  {
154  }
155 
156  std::string m_name;
159  uint16_t m_width;
160  double m_snrLow;
161  double m_snrHigh;
162  double m_xMin;
163  double m_xMax;
164  double m_yMax;
165 };
166 
176 void
178  Step step,
179  double rss,
180  Gnuplot2dDataset& rateDataset,
181  Gnuplot2dDataset& actualDataset)
182 {
183  NS_LOG_FUNCTION(rssModel << step.stepSize << step.stepTime << rss);
184  double snr = rss - noiseDbm;
185  rateDataset.Add(snr, g_intervalRate / 1e6);
186  // Calculate received rate since last interval
187  double currentRate = ((g_intervalBytes * 8) / step.stepTime) / 1e6; // Mb/s
188  actualDataset.Add(snr, currentRate);
189  rssModel->SetRss(rss - step.stepSize);
190  NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << "; selected rate "
191  << (g_intervalRate / 1e6) << "; observed rate " << currentRate
192  << "; setting new power to " << rss - step.stepSize);
193  g_intervalBytes = 0;
196  rssModel,
197  step,
198  (rss - step.stepSize),
199  rateDataset,
200  actualDataset);
201 }
202 
203 int
204 main(int argc, char* argv[])
205 {
206  std::vector<StandardInfo> serverStandards;
207  std::vector<StandardInfo> clientStandards;
208  uint32_t steps;
209  uint32_t rtsThreshold = 999999; // disabled even for large A-MPDU
210  uint32_t maxAmpduSize = 65535;
211  double stepSize = 1; // dBm
212  double stepTime = 1; // seconds
213  uint32_t packetSize = 1024; // bytes
214  bool broadcast = false;
215  int ap1_x = 0;
216  int ap1_y = 0;
217  int sta1_x = 5;
218  int sta1_y = 0;
219  uint16_t serverNss = 1;
220  uint16_t clientNss = 1;
221  uint16_t serverShortGuardInterval = 800;
222  uint16_t clientShortGuardInterval = 800;
223  uint16_t serverChannelWidth = 0; // use default for standard and band
224  uint16_t clientChannelWidth = 0; // use default for standard and band
225  std::string wifiManager("Ideal");
226  std::string standard("802.11a");
227  StandardInfo serverSelectedStandard;
228  StandardInfo clientSelectedStandard;
229  bool infrastructure = false;
230  uint32_t maxSlrc = 7;
231  uint32_t maxSsrc = 7;
232 
233  CommandLine cmd(__FILE__);
234  cmd.AddValue("maxSsrc",
235  "The maximum number of retransmission attempts for a RTS packet",
236  maxSsrc);
237  cmd.AddValue("maxSlrc",
238  "The maximum number of retransmission attempts for a Data packet",
239  maxSlrc);
240  cmd.AddValue("rtsThreshold", "RTS threshold", rtsThreshold);
241  cmd.AddValue("maxAmpduSize", "Max A-MPDU size", maxAmpduSize);
242  cmd.AddValue("stepSize", "Power between steps (dBm)", stepSize);
243  cmd.AddValue("stepTime", "Time on each step (seconds)", stepTime);
244  cmd.AddValue("broadcast", "Send broadcast instead of unicast", broadcast);
245  cmd.AddValue("serverChannelWidth",
246  "Set channel width of the server (valid only for 802.11n or ac)",
247  serverChannelWidth);
248  cmd.AddValue("clientChannelWidth",
249  "Set channel width of the client (valid only for 802.11n or ac)",
250  clientChannelWidth);
251  cmd.AddValue("serverNss", "Set nss of the server (valid only for 802.11n or ac)", serverNss);
252  cmd.AddValue("clientNss", "Set nss of the client (valid only for 802.11n or ac)", clientNss);
253  cmd.AddValue("serverShortGuardInterval",
254  "Set short guard interval of the server (802.11n/ac/ax) in nanoseconds",
255  serverShortGuardInterval);
256  cmd.AddValue("clientShortGuardInterval",
257  "Set short guard interval of the client (802.11n/ac/ax) in nanoseconds",
258  clientShortGuardInterval);
259  cmd.AddValue(
260  "standard",
261  "Set standard (802.11a, 802.11b, 802.11g, 802.11p-10MHz, 802.11p-5MHz, 802.11n-5GHz, "
262  "802.11n-2.4GHz, 802.11ac, 802.11ax-6GHz, 802.11ax-5GHz, 802.11ax-2.4GHz)",
263  standard);
264  cmd.AddValue("wifiManager",
265  "Set wifi rate manager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, "
266  "MinstrelHt, Onoe, Rraa, ThompsonSampling)",
267  wifiManager);
268  cmd.AddValue("infrastructure", "Use infrastructure instead of adhoc", infrastructure);
269  cmd.Parse(argc, argv);
270 
271  // Print out some explanation of what this program does
272  std::cout << std::endl
273  << "This program demonstrates and plots the operation of different " << std::endl;
274  std::cout << "Wi-Fi rate controls on different station configurations," << std::endl;
275  std::cout << "by stepping down the received signal strength across a wide range" << std::endl;
276  std::cout << "and observing the adjustment of the rate." << std::endl;
277  std::cout << "Run 'wifi-manager-example --PrintHelp' to show program options." << std::endl
278  << std::endl;
279 
280  if (!infrastructure)
281  {
282  NS_ABORT_MSG_IF(serverNss != clientNss,
283  "In ad hoc mode, we assume sender and receiver are similarly configured");
284  }
285 
286  if (standard == "802.11b")
287  {
288  if (serverChannelWidth == 0)
289  {
291  }
292  NS_ABORT_MSG_IF(serverChannelWidth != 22,
293  "Invalid channel width for standard " << standard);
294  NS_ABORT_MSG_IF(serverNss != 1, "Invalid nss for standard " << standard);
295  if (clientChannelWidth == 0)
296  {
298  }
299  NS_ABORT_MSG_IF(clientChannelWidth != 22,
300  "Invalid channel width for standard " << standard);
301  NS_ABORT_MSG_IF(clientNss != 1, "Invalid nss for standard " << standard);
302  }
303  else if (standard == "802.11a" || standard == "802.11g")
304  {
305  if (serverChannelWidth == 0)
306  {
308  }
309  NS_ABORT_MSG_IF(serverChannelWidth != 20,
310  "Invalid channel width for standard " << standard);
311  NS_ABORT_MSG_IF(serverNss != 1, "Invalid nss for standard " << standard);
312  if (clientChannelWidth == 0)
313  {
315  }
316  NS_ABORT_MSG_IF(clientChannelWidth != 20,
317  "Invalid channel width for standard " << standard);
318  NS_ABORT_MSG_IF(clientNss != 1, "Invalid nss for standard " << standard);
319  }
320  else if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz")
321  {
322  WifiPhyBand band =
323  (standard == "802.11n-2.4GHz" ? WIFI_PHY_BAND_2_4GHZ : WIFI_PHY_BAND_5GHZ);
324  if (serverChannelWidth == 0)
325  {
326  serverChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211n, band);
327  }
328  NS_ABORT_MSG_IF(serverChannelWidth != 20 && serverChannelWidth != 40,
329  "Invalid channel width for standard " << standard);
330  NS_ABORT_MSG_IF(serverNss == 0 || serverNss > 4,
331  "Invalid nss " << serverNss << " for standard " << standard);
332  if (clientChannelWidth == 0)
333  {
334  clientChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211n, band);
335  }
336  NS_ABORT_MSG_IF(clientChannelWidth != 20 && clientChannelWidth != 40,
337  "Invalid channel width for standard " << standard);
338  NS_ABORT_MSG_IF(clientNss == 0 || clientNss > 4,
339  "Invalid nss " << clientNss << " for standard " << standard);
340  }
341  else if (standard == "802.11ac")
342  {
343  if (serverChannelWidth == 0)
344  {
346  }
347  NS_ABORT_MSG_IF(serverChannelWidth != 20 && serverChannelWidth != 40 &&
348  serverChannelWidth != 80 && serverChannelWidth != 160,
349  "Invalid channel width for standard " << standard);
350  NS_ABORT_MSG_IF(serverNss == 0 || serverNss > 4,
351  "Invalid nss " << serverNss << " for standard " << standard);
352  if (clientChannelWidth == 0)
353  {
355  }
356  NS_ABORT_MSG_IF(clientChannelWidth != 20 && clientChannelWidth != 40 &&
357  clientChannelWidth != 80 && clientChannelWidth != 160,
358  "Invalid channel width for standard " << standard);
359  NS_ABORT_MSG_IF(clientNss == 0 || clientNss > 4,
360  "Invalid nss " << clientNss << " for standard " << standard);
361  }
362  else if (standard == "802.11ax-6GHz" || standard == "802.11ax-5GHz" ||
363  standard == "802.11ax-2.4GHz")
364  {
365  WifiPhyBand band = (standard == "802.11ax-2.4GHz" ? WIFI_PHY_BAND_2_4GHZ
366  : standard == "802.11ax-6GHz" ? WIFI_PHY_BAND_6GHZ
368  if (serverChannelWidth == 0)
369  {
370  serverChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211ax, band);
371  }
372  NS_ABORT_MSG_IF(serverChannelWidth != 20 && serverChannelWidth != 40 &&
373  serverChannelWidth != 80 && serverChannelWidth != 160,
374  "Invalid channel width for standard " << standard);
375  NS_ABORT_MSG_IF(serverNss == 0 || serverNss > 4,
376  "Invalid nss " << serverNss << " for standard " << standard);
377  if (clientChannelWidth == 0)
378  {
379  clientChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211ax, band);
380  }
381  NS_ABORT_MSG_IF(clientChannelWidth != 20 && clientChannelWidth != 40 &&
382  clientChannelWidth != 80 && clientChannelWidth != 160,
383  "Invalid channel width for standard " << standard);
384  NS_ABORT_MSG_IF(clientNss == 0 || clientNss > 4,
385  "Invalid nss " << clientNss << " for standard " << standard);
386  }
387 
388  // As channel width increases, scale up plot's yRange value
389  uint32_t channelRateFactor = std::max(clientChannelWidth, serverChannelWidth) / 20;
390  channelRateFactor = channelRateFactor * std::max(clientNss, serverNss);
391 
392  // The first number is channel width, second is minimum SNR, third is maximum
393  // SNR, fourth and fifth provide xrange axis limits, and sixth the yaxis
394  // maximum
395  serverStandards = {
396  StandardInfo("802.11a", WIFI_STANDARD_80211a, WIFI_PHY_BAND_5GHZ, 20, 3, 27, 0, 30, 60),
397  StandardInfo("802.11b", WIFI_STANDARD_80211b, WIFI_PHY_BAND_2_4GHZ, 22, -5, 11, -6, 15, 15),
398  StandardInfo("802.11g", WIFI_STANDARD_80211g, WIFI_PHY_BAND_2_4GHZ, 20, -5, 27, -6, 30, 60),
399  StandardInfo("802.11n-5GHz",
402  serverChannelWidth,
403  3,
404  30,
405  0,
406  35,
407  80 * channelRateFactor),
408  StandardInfo("802.11n-2.4GHz",
411  serverChannelWidth,
412  3,
413  30,
414  0,
415  35,
416  80 * channelRateFactor),
417  StandardInfo("802.11ac",
420  serverChannelWidth,
421  5,
422  50,
423  0,
424  55,
425  120 * channelRateFactor),
426  StandardInfo("802.11p-10MHz",
429  10,
430  3,
431  27,
432  0,
433  30,
434  60),
435  StandardInfo("802.11p-5MHz", WIFI_STANDARD_80211p, WIFI_PHY_BAND_5GHZ, 5, 3, 27, 0, 30, 60),
436  StandardInfo("802.11ax-6GHz",
439  serverChannelWidth,
440  5,
441  55,
442  0,
443  60,
444  120 * channelRateFactor),
445  StandardInfo("802.11ax-5GHz",
448  serverChannelWidth,
449  5,
450  55,
451  0,
452  60,
453  120 * channelRateFactor),
454  StandardInfo("802.11ax-2.4GHz",
457  serverChannelWidth,
458  5,
459  55,
460  0,
461  60,
462  120 * channelRateFactor),
463  };
464 
465  clientStandards = {
466  StandardInfo("802.11a", WIFI_STANDARD_80211a, WIFI_PHY_BAND_5GHZ, 20, 3, 27, 0, 30, 60),
467  StandardInfo("802.11b", WIFI_STANDARD_80211b, WIFI_PHY_BAND_2_4GHZ, 22, -5, 11, -6, 15, 15),
468  StandardInfo("802.11g", WIFI_STANDARD_80211g, WIFI_PHY_BAND_2_4GHZ, 20, -5, 27, -6, 30, 60),
469  StandardInfo("802.11n-5GHz",
472  clientChannelWidth,
473  3,
474  30,
475  0,
476  35,
477  80 * channelRateFactor),
478  StandardInfo("802.11n-2.4GHz",
481  clientChannelWidth,
482  3,
483  30,
484  0,
485  35,
486  80 * channelRateFactor),
487  StandardInfo("802.11ac",
490  clientChannelWidth,
491  5,
492  50,
493  0,
494  55,
495  120 * channelRateFactor),
496  StandardInfo("802.11p-10MHz",
499  10,
500  3,
501  27,
502  0,
503  30,
504  60),
505  StandardInfo("802.11p-5MHz", WIFI_STANDARD_80211p, WIFI_PHY_BAND_5GHZ, 5, 3, 27, 0, 30, 60),
506  StandardInfo("802.11ax-6GHz",
509  clientChannelWidth,
510  5,
511  55,
512  0,
513  60,
514  160 * channelRateFactor),
515  StandardInfo("802.11ax-5GHz",
518  clientChannelWidth,
519  5,
520  55,
521  0,
522  60,
523  160 * channelRateFactor),
524  StandardInfo("802.11ax-2.4GHz",
527  clientChannelWidth,
528  5,
529  55,
530  0,
531  60,
532  160 * channelRateFactor),
533  };
534 
535  for (std::vector<StandardInfo>::size_type i = 0; i != serverStandards.size(); i++)
536  {
537  if (standard == serverStandards[i].m_name)
538  {
539  serverSelectedStandard = serverStandards[i];
540  }
541  }
542  for (std::vector<StandardInfo>::size_type i = 0; i != clientStandards.size(); i++)
543  {
544  if (standard == clientStandards[i].m_name)
545  {
546  clientSelectedStandard = clientStandards[i];
547  }
548  }
549 
550  NS_ABORT_MSG_IF(serverSelectedStandard.m_name == "none",
551  "Standard " << standard << " not found");
552  NS_ABORT_MSG_IF(clientSelectedStandard.m_name == "none",
553  "Standard " << standard << " not found");
554  std::cout << "Testing " << serverSelectedStandard.m_name << " with " << wifiManager << " ..."
555  << std::endl;
556  NS_ABORT_MSG_IF(clientSelectedStandard.m_snrLow >= clientSelectedStandard.m_snrHigh,
557  "SNR values in wrong order");
558  steps = static_cast<uint32_t>(std::abs(static_cast<double>(clientSelectedStandard.m_snrHigh -
559  clientSelectedStandard.m_snrLow) /
560  stepSize) +
561  1);
562  NS_LOG_DEBUG("Using " << steps << " steps for SNR range " << clientSelectedStandard.m_snrLow
563  << ":" << clientSelectedStandard.m_snrHigh);
564  Ptr<Node> clientNode = CreateObject<Node>();
565  Ptr<Node> serverNode = CreateObject<Node>();
566 
567  std::string plotName = "wifi-manager-example-";
568  std::string dataName = "wifi-manager-example-";
569  plotName += wifiManager;
570  dataName += wifiManager;
571  plotName += "-";
572  dataName += "-";
573  plotName += standard;
574  dataName += standard;
575  if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz" || standard == "802.11ac" ||
576  standard == "802.11ax-6GHz" || standard == "802.11ax-5GHz" || standard == "802.11ax-2.4GHz")
577  {
578  plotName += "-server_";
579  dataName += "-server_";
580  std::ostringstream oss;
581  oss << serverChannelWidth << "MHz_" << serverShortGuardInterval << "ns_" << serverNss
582  << "SS";
583  plotName += oss.str();
584  dataName += oss.str();
585  plotName += "-client_";
586  dataName += "-client_";
587  oss.str("");
588  oss << clientChannelWidth << "MHz_" << clientShortGuardInterval << "ns_" << clientNss
589  << "SS";
590  plotName += oss.str();
591  dataName += oss.str();
592  }
593  plotName += ".eps";
594  dataName += ".plt";
595  std::ofstream outfile(dataName);
596  Gnuplot gnuplot = Gnuplot(plotName);
597 
598  Config::SetDefault("ns3::WifiRemoteStationManager::MaxSlrc", UintegerValue(maxSlrc));
599  Config::SetDefault("ns3::WifiRemoteStationManager::MaxSsrc", UintegerValue(maxSsrc));
600  Config::SetDefault("ns3::MinstrelWifiManager::PrintStats", BooleanValue(true));
601  Config::SetDefault("ns3::MinstrelWifiManager::PrintSamples", BooleanValue(true));
602  Config::SetDefault("ns3::MinstrelHtWifiManager::PrintStats", BooleanValue(true));
603 
604  // Disable the default noise figure of 7 dBm in WifiPhy; the calculations
605  // of SNR below assume that the only noise is thermal noise
606  Config::SetDefault("ns3::WifiPhy::RxNoiseFigure", DoubleValue(0));
607 
608  // By default, the CCA sensitivity is -82 dBm, meaning if the RSS is
609  // below this value, the receiver will reject the Wi-Fi frame.
610  // However, we want to probe the error model down to low SNR values,
611  // and we have disabled the noise figure, so the noise level in 20 MHz
612  // will be about -101 dBm. Therefore, lower the CCA sensitivity to a
613  // value that disables it (e.g. -110 dBm)
614  Config::SetDefault("ns3::WifiPhy::CcaSensitivity", DoubleValue(-110));
615 
617  wifi.SetStandard(serverSelectedStandard.m_standard);
618  YansWifiPhyHelper wifiPhy;
619  // Disable the preamble detection model for the same reason that we
620  // disabled CCA sensitivity above-- we want to enable reception at low SNR
622 
623  Ptr<YansWifiChannel> wifiChannel = CreateObject<YansWifiChannel>();
625  CreateObject<ConstantSpeedPropagationDelayModel>();
626  wifiChannel->SetPropagationDelayModel(delayModel);
627  Ptr<FixedRssLossModel> rssLossModel = CreateObject<FixedRssLossModel>();
628  wifiChannel->SetPropagationLossModel(rssLossModel);
629  wifiPhy.SetChannel(wifiChannel);
630 
631  wifi.SetRemoteStationManager("ns3::" + wifiManager + "WifiManager",
632  "RtsCtsThreshold",
633  UintegerValue(rtsThreshold));
634 
635  NetDeviceContainer serverDevice;
636  NetDeviceContainer clientDevice;
637 
639 
640  WifiMacHelper wifiMac;
641  if (infrastructure)
642  {
643  Ssid ssid = Ssid("ns-3-ssid");
644  wifiMac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
645  channelValue.Set(WifiPhy::ChannelTuple{0,
646  serverSelectedStandard.m_width,
647  serverSelectedStandard.m_band,
648  0});
649  wifiPhy.Set("ChannelSettings", channelValue);
650  serverDevice = wifi.Install(wifiPhy, wifiMac, serverNode);
651 
652  wifiMac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
653  channelValue.Set(WifiPhy::ChannelTuple{0,
654  clientSelectedStandard.m_width,
655  clientSelectedStandard.m_band,
656  0});
657  clientDevice = wifi.Install(wifiPhy, wifiMac, clientNode);
658  }
659  else
660  {
661  wifiMac.SetType("ns3::AdhocWifiMac");
662  channelValue.Set(WifiPhy::ChannelTuple{0,
663  serverSelectedStandard.m_width,
664  serverSelectedStandard.m_band,
665  0});
666  wifiPhy.Set("ChannelSettings", channelValue);
667  serverDevice = wifi.Install(wifiPhy, wifiMac, serverNode);
668 
669  channelValue.Set(WifiPhy::ChannelTuple{0,
670  clientSelectedStandard.m_width,
671  clientSelectedStandard.m_band,
672  0});
673  clientDevice = wifi.Install(wifiPhy, wifiMac, clientNode);
674  }
675 
678  wifi.AssignStreams(serverDevice, 100);
679  wifi.AssignStreams(clientDevice, 100);
680 
681  Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
682  UintegerValue(maxAmpduSize));
683 
685  "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager +
686  "WifiManager/Rate",
688 
689  // Configure the mobility.
691  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
692  // Initial position of AP and STA
693  positionAlloc->Add(Vector(ap1_x, ap1_y, 0.0));
694  NS_LOG_INFO("Setting initial AP position to " << Vector(ap1_x, ap1_y, 0.0));
695  positionAlloc->Add(Vector(sta1_x, sta1_y, 0.0));
696  NS_LOG_INFO("Setting initial STA position to " << Vector(sta1_x, sta1_y, 0.0));
697  mobility.SetPositionAllocator(positionAlloc);
698  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
699  mobility.Install(clientNode);
700  mobility.Install(serverNode);
701 
702  Gnuplot2dDataset rateDataset(clientSelectedStandard.m_name + std::string("-rate selected"));
703  Gnuplot2dDataset actualDataset(clientSelectedStandard.m_name + std::string("-observed"));
704  Step step;
705  step.stepSize = stepSize;
706  step.stepTime = stepTime;
707 
708  // Perform post-install configuration from defaults for channel width,
709  // guard interval, and nss, if necessary
710  // Obtain pointer to the WifiPhy
711  Ptr<NetDevice> ndClient = clientDevice.Get(0);
712  Ptr<NetDevice> ndServer = serverDevice.Get(0);
713  Ptr<WifiNetDevice> wndClient = ndClient->GetObject<WifiNetDevice>();
714  Ptr<WifiNetDevice> wndServer = ndServer->GetObject<WifiNetDevice>();
715  Ptr<WifiPhy> wifiPhyPtrClient = wndClient->GetPhy();
716  Ptr<WifiPhy> wifiPhyPtrServer = wndServer->GetPhy();
717  auto t_clientNss = static_cast<uint8_t>(clientNss);
718  auto t_serverNss = static_cast<uint8_t>(serverNss);
719  wifiPhyPtrClient->SetNumberOfAntennas(t_clientNss);
720  wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams(t_clientNss);
721  wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams(t_clientNss);
722  wifiPhyPtrServer->SetNumberOfAntennas(t_serverNss);
723  wifiPhyPtrServer->SetMaxSupportedTxSpatialStreams(t_serverNss);
724  wifiPhyPtrServer->SetMaxSupportedRxSpatialStreams(t_serverNss);
725  // Only set the guard interval for HT and VHT modes
726  if (serverSelectedStandard.m_name == "802.11n-5GHz" ||
727  serverSelectedStandard.m_name == "802.11n-2.4GHz" ||
728  serverSelectedStandard.m_name == "802.11ac")
729  {
730  Ptr<HtConfiguration> clientHtConfiguration = wndClient->GetHtConfiguration();
731  clientHtConfiguration->SetShortGuardIntervalSupported(clientShortGuardInterval == 400);
732  Ptr<HtConfiguration> serverHtConfiguration = wndServer->GetHtConfiguration();
733  serverHtConfiguration->SetShortGuardIntervalSupported(serverShortGuardInterval == 400);
734  }
735  else if (serverSelectedStandard.m_name == "802.11ax-6GHz" ||
736  serverSelectedStandard.m_name == "802.11ax-5GHz" ||
737  serverSelectedStandard.m_name == "802.11ax-2.4GHz")
738  {
739  wndServer->GetHeConfiguration()->SetGuardInterval(NanoSeconds(serverShortGuardInterval));
740  wndClient->GetHeConfiguration()->SetGuardInterval(NanoSeconds(clientShortGuardInterval));
741  }
742  NS_LOG_DEBUG("Channel width " << wifiPhyPtrClient->GetChannelWidth() << " noiseDbm "
743  << noiseDbm);
744  NS_LOG_DEBUG("NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams());
745 
746  // Configure signal and noise, and schedule first iteration
747  noiseDbm += 10 * log10(clientSelectedStandard.m_width * 1000000);
748  double rssCurrent = (clientSelectedStandard.m_snrHigh + noiseDbm);
749  rssLossModel->SetRss(rssCurrent);
750  NS_LOG_INFO("Setting initial Rss to " << rssCurrent);
751  // Move the STA by stepsSize meters every stepTime seconds
752  Simulator::Schedule(Seconds(0.5 + stepTime),
754  rssLossModel,
755  step,
756  rssCurrent,
757  rateDataset,
758  actualDataset);
759 
760  PacketSocketHelper packetSocketHelper;
761  packetSocketHelper.Install(serverNode);
762  packetSocketHelper.Install(clientNode);
763 
764  PacketSocketAddress socketAddr;
765  socketAddr.SetSingleDevice(serverDevice.Get(0)->GetIfIndex());
766  if (broadcast)
767  {
768  socketAddr.SetPhysicalAddress(serverDevice.Get(0)->GetBroadcast());
769  }
770  else
771  {
772  socketAddr.SetPhysicalAddress(serverDevice.Get(0)->GetAddress());
773  }
774  // Arbitrary protocol type.
775  // Note: PacketSocket doesn't have any L4 multiplexing or demultiplexing
776  // The only mux/demux is based on the protocol field
777  socketAddr.SetProtocol(1);
778 
779  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
780  client->SetRemote(socketAddr);
781  client->SetStartTime(Seconds(0.5)); // allow simulation warmup
782  client->SetAttribute("MaxPackets", UintegerValue(0)); // unlimited
783  client->SetAttribute("PacketSize", UintegerValue(packetSize));
784 
785  // Set a maximum rate 10% above the yMax specified for the selected standard
786  double rate = clientSelectedStandard.m_yMax * 1e6 * 1.10;
787  double clientInterval = static_cast<double>(packetSize) * 8 / rate;
788  NS_LOG_DEBUG("Setting interval to " << clientInterval << " sec for rate of " << rate
789  << " bits/sec");
790 
791  client->SetAttribute("Interval", TimeValue(Seconds(clientInterval)));
792  clientNode->AddApplication(client);
793 
794  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
795  server->SetLocal(socketAddr);
796  server->TraceConnectWithoutContext("Rx", MakeCallback(&PacketRx));
797  serverNode->AddApplication(server);
798 
799  Simulator::Stop(Seconds((steps + 1) * stepTime));
800  Simulator::Run();
802 
803  gnuplot.AddDataset(rateDataset);
804  gnuplot.AddDataset(actualDataset);
805 
806  std::ostringstream xMinStr;
807  std::ostringstream xMaxStr;
808  std::ostringstream yMaxStr;
809  std::string xRangeStr("set xrange [");
810  xMinStr << clientSelectedStandard.m_xMin;
811  xRangeStr.append(xMinStr.str());
812  xRangeStr.append(":");
813  xMaxStr << clientSelectedStandard.m_xMax;
814  xRangeStr.append(xMaxStr.str());
815  xRangeStr.append("]");
816  std::string yRangeStr("set yrange [0:");
817  yMaxStr << clientSelectedStandard.m_yMax;
818  yRangeStr.append(yMaxStr.str());
819  yRangeStr.append("]");
820 
821  std::string title("Results for ");
822  title.append(standard);
823  title.append(" with ");
824  title.append(wifiManager);
825  title.append("\\n");
826  if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz" || standard == "802.11ac" ||
827  standard == "802.11ax-6GHz" || standard == "802.11ax-5GHz" || standard == "802.11ax-2.4GHz")
828  {
829  std::ostringstream serverGiStrStr;
830  std::ostringstream serverWidthStrStr;
831  std::ostringstream serverNssStrStr;
832  title.append("server: width=");
833  serverWidthStrStr << serverSelectedStandard.m_width;
834  title.append(serverWidthStrStr.str());
835  title.append("MHz");
836  title.append(" GI=");
837  serverGiStrStr << serverShortGuardInterval;
838  title.append(serverGiStrStr.str());
839  title.append("ns");
840  title.append(" nss=");
841  serverNssStrStr << serverNss;
842  title.append(serverNssStrStr.str());
843  title.append("\\n");
844  std::ostringstream clientGiStrStr;
845  std::ostringstream clientWidthStrStr;
846  std::ostringstream clientNssStrStr;
847  title.append("client: width=");
848  clientWidthStrStr << clientSelectedStandard.m_width;
849  title.append(clientWidthStrStr.str());
850  title.append("MHz");
851  title.append(" GI=");
852  clientGiStrStr << clientShortGuardInterval;
853  title.append(clientGiStrStr.str());
854  title.append("ns");
855  title.append(" nss=");
856  clientNssStrStr << clientNss;
857  title.append(clientNssStrStr.str());
858  }
859  gnuplot.SetTerminal("postscript eps color enh \"Times-BoldItalic\"");
860  gnuplot.SetLegend("SNR (dB)", "Rate (Mb/s)");
861  gnuplot.SetTitle(title);
862  gnuplot.SetExtra(xRangeStr);
863  gnuplot.AppendExtra(yRangeStr);
864  gnuplot.AppendExtra("set key top left");
865  gnuplot.GenerateOutput(outfile);
866  outfile.close();
867 
868  return 0;
869 }
#define max(a, b)
Definition: 80211b.c:42
a polymophic address class
Definition: address.h:101
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
void Add(double x, double y)
Definition: gnuplot.cc:362
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 AppendExtra(const std::string &extra)
Definition: gnuplot.cc:752
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
void SetTitle(const std::string &title)
Definition: gnuplot.cc:733
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.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:169
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
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 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 Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
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
@ S
second
Definition: nstime.h:116
Hold objects of type std::tuple<Args...>.
Definition: tuple.h:69
void Set(const result_type &value)
Set the stored values.
Definition: tuple.h:318
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)
Hold together all Wifi-related objects.
Ptr< HtConfiguration > GetHtConfiguration() const
Ptr< HeConfiguration > GetHeConfiguration() const
Ptr< WifiPhy > GetPhy() const
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
void SetNumberOfAntennas(uint8_t antennas)
Definition: wifi-phy.cc:1257
void SetMaxSupportedRxSpatialStreams(uint8_t streams)
Definition: wifi-phy.cc:1307
void SetMaxSupportedTxSpatialStreams(uint8_t streams)
Definition: wifi-phy.cc:1275
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:891
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:890
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:950
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:876
#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:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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:275
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
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.
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:704
uint16_t GetDefaultChannelWidth(WifiStandard standard, WifiPhyBand band)
Get the default channel width for the given PHY standard and band.
cmd
Definition: second.py:40
ssid
Definition: third.py:93
wifi
Definition: third.py:95
mobility
Definition: third.py:105
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
Rate in an interval.
void RateChange(uint64_t oldVal, uint64_t newVal)
Rate changed.
const double NOISE_DBM_Hz
Default value for noise.
void PacketRx(Ptr< const Packet > pkt, const Address &addr)
Packet received.
double g_intervalBytes
Bytes received in an interval.
double noiseDbm
Value for noise.
void ChangeSignalAndReportRate(Ptr< FixedRssLossModel > rssModel, Step step, double rss, Gnuplot2dDataset &rateDataset, Gnuplot2dDataset &actualDataset)
Change the signal model and report the rate.
static const uint32_t packetSize
Packet size generated at the AP.