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