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 MHz_u serverChannelWidth{0}; // use default for standard and band
214 MHz_u 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 maxRetryCount = 7;
221
224
225 CommandLine cmd(__FILE__);
226 cmd.AddValue("maxRetryCount",
227 "The maximum number of retransmission attempts for a Data packet",
228 maxRetryCount);
229 cmd.AddValue("rtsThreshold", "RTS threshold", rtsThreshold);
230 cmd.AddValue("maxAmpduSize", "Max A-MPDU size", maxAmpduSize);
231 cmd.AddValue("stepSize", "Power between steps (dBm)", stepSize);
232 cmd.AddValue("stepTime", "Time on each step (seconds)", stepTime);
233 cmd.AddValue("broadcast", "Send broadcast instead of unicast", broadcast);
234 cmd.AddValue("serverChannelWidth",
235 "Set channel width of the server (valid only for 802.11n or ac)",
236 serverChannelWidth);
237 cmd.AddValue("clientChannelWidth",
238 "Set channel width of the client (valid only for 802.11n or ac)",
239 clientChannelWidth);
240 cmd.AddValue("serverNss", "Set nss of the server (valid only for 802.11n or ac)", serverNss);
241 cmd.AddValue("clientNss", "Set nss of the client (valid only for 802.11n or ac)", clientNss);
242 cmd.AddValue("serverShortGuardInterval",
243 "Set short guard interval of the server (802.11n/ac/ax) in nanoseconds",
244 serverShortGuardInterval);
245 cmd.AddValue("clientShortGuardInterval",
246 "Set short guard interval of the client (802.11n/ac/ax) in nanoseconds",
247 clientShortGuardInterval);
248 cmd.AddValue(
249 "standard",
250 "Set standard (802.11a, 802.11b, 802.11g, 802.11p-10MHz, 802.11p-5MHz, 802.11n-5GHz, "
251 "802.11n-2.4GHz, 802.11ac, 802.11ax-6GHz, 802.11ax-5GHz, 802.11ax-2.4GHz, 802.11be-6GHz, "
252 "802.11be-5GHz, 802.11be-2.4GHz)",
253 standard);
254 cmd.AddValue("wifiManager",
255 "Set wifi rate manager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, "
256 "MinstrelHt, Onoe, Rraa, ThompsonSampling)",
257 wifiManager);
258 cmd.AddValue("infrastructure", "Use infrastructure instead of adhoc", infrastructure);
259 cmd.Parse(argc, argv);
260
261 // Print out some explanation of what this program does
262 std::cout << std::endl
263 << "This program demonstrates and plots the operation of different " << std::endl;
264 std::cout << "Wi-Fi rate controls on different station configurations," << std::endl;
265 std::cout << "by stepping down the received signal strength across a wide range" << std::endl;
266 std::cout << "and observing the adjustment of the rate." << std::endl;
267 std::cout << "Run 'wifi-manager-example --PrintHelp' to show program options." << std::endl
268 << std::endl;
269
270 if (!infrastructure)
271 {
272 NS_ABORT_MSG_IF(serverNss != clientNss,
273 "In ad hoc mode, we assume sender and receiver are similarly configured");
274 }
275
276 if (standard == "802.11b")
277 {
278 if (serverChannelWidth == MHz_u{0})
279 {
281 }
282 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{22},
283 "Invalid channel width for standard " << standard);
284 NS_ABORT_MSG_IF(serverNss != 1, "Invalid nss for standard " << standard);
285 if (clientChannelWidth == MHz_u{0})
286 {
288 }
289 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{22},
290 "Invalid channel width for standard " << standard);
291 NS_ABORT_MSG_IF(clientNss != 1, "Invalid nss for standard " << standard);
292 }
293 else if (standard == "802.11a" || standard == "802.11g")
294 {
295 if (serverChannelWidth == MHz_u{0})
296 {
298 }
299 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{20},
300 "Invalid channel width for standard " << standard);
301 NS_ABORT_MSG_IF(serverNss != 1, "Invalid nss for standard " << standard);
302 if (clientChannelWidth == MHz_u{0})
303 {
305 }
306 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{20},
307 "Invalid channel width for standard " << standard);
308 NS_ABORT_MSG_IF(clientNss != 1, "Invalid nss for standard " << standard);
309 }
310 else if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz")
311 {
312 WifiPhyBand band =
313 (standard == "802.11n-2.4GHz" ? WIFI_PHY_BAND_2_4GHZ : WIFI_PHY_BAND_5GHZ);
314 if (serverChannelWidth == MHz_u{0})
315 {
316 serverChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211n, band);
317 }
318 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{20} && serverChannelWidth != MHz_u{40},
319 "Invalid channel width for standard " << standard);
320 NS_ABORT_MSG_IF(serverNss == 0 || serverNss > 4,
321 "Invalid nss " << serverNss << " for standard " << standard);
322 if (clientChannelWidth == MHz_u{0})
323 {
324 clientChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211n, band);
325 }
326 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{20} && clientChannelWidth != MHz_u{40},
327 "Invalid channel width for standard " << standard);
328 NS_ABORT_MSG_IF(clientNss == 0 || clientNss > 4,
329 "Invalid nss " << clientNss << " for standard " << standard);
330 }
331 else if (standard == "802.11ac")
332 {
333 if (serverChannelWidth == MHz_u{0})
334 {
336 }
337 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{20} && serverChannelWidth != MHz_u{40} &&
338 serverChannelWidth != MHz_u{80} && serverChannelWidth != MHz_u{160} &&
339 serverChannelWidth != MHz_u{320},
340 "Invalid channel width for standard " << standard);
341 NS_ABORT_MSG_IF(serverNss == 0 || serverNss > 4,
342 "Invalid nss " << serverNss << " for standard " << standard);
343 if (clientChannelWidth == MHz_u{0})
344 {
346 }
347 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{20} && clientChannelWidth != MHz_u{40} &&
348 clientChannelWidth != MHz_u{80} && clientChannelWidth != MHz_u{160} &&
349 clientChannelWidth != MHz_u{320},
350 "Invalid channel width for standard " << standard);
351 NS_ABORT_MSG_IF(clientNss == 0 || clientNss > 4,
352 "Invalid nss " << clientNss << " for standard " << standard);
353 }
354 else if (standard == "802.11ax-6GHz" || standard == "802.11ax-5GHz" ||
355 standard == "802.11ax-2.4GHz" || standard == "802.11be-6GHz" ||
356 standard == "802.11be-5GHz" || standard == "802.11be-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 == MHz_u{0})
362 {
363 serverChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211ax, band);
364 }
365 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{20} && serverChannelWidth != MHz_u{40} &&
366 serverChannelWidth != MHz_u{80} && serverChannelWidth != MHz_u{160} &&
367 serverChannelWidth != MHz_u{320},
368 "Invalid channel width for standard " << standard);
369 NS_ABORT_MSG_IF(serverNss == 0 || serverNss > 4,
370 "Invalid nss " << serverNss << " for standard " << standard);
371 if (clientChannelWidth == MHz_u{0})
372 {
373 clientChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211ax, band);
374 }
375 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{20} && clientChannelWidth != MHz_u{40} &&
376 clientChannelWidth != MHz_u{80} && clientChannelWidth != MHz_u{160} &&
377 clientChannelWidth != MHz_u{320},
378 "Invalid channel width for standard " << standard);
379 NS_ABORT_MSG_IF(clientNss == 0 || clientNss > 4,
380 "Invalid nss " << clientNss << " for standard " << standard);
381 }
382
383 // As channel width increases, scale up plot's yRange value
384 uint32_t channelRateFactor = std::max(clientChannelWidth, serverChannelWidth) / MHz_u{20};
385 channelRateFactor = channelRateFactor * std::max(clientNss, serverNss);
386
387 // The first number is channel width, second is minimum SNR, third is maximum
388 // SNR, fourth and fifth provide xrange axis limits, and sixth the yaxis
389 // maximum
390 serverStandards = {
391 StandardInfo("802.11a",
394 MHz_u{20},
395 dB_u{3},
396 dB_u{27},
397 0,
398 30,
399 60),
400 StandardInfo("802.11b",
403 MHz_u{22},
404 dB_u{-5},
405 dB_u{11},
406 -6,
407 15,
408 15),
409 StandardInfo("802.11g",
412 MHz_u{20},
413 dB_u{-5},
414 dB_u{27},
415 -6,
416 30,
417 60),
418 StandardInfo("802.11n-5GHz",
421 serverChannelWidth,
422 dB_u{3},
423 dB_u{30},
424 0,
425 35,
426 80 * channelRateFactor),
427 StandardInfo("802.11n-2.4GHz",
430 serverChannelWidth,
431 dB_u{3},
432 dB_u{30},
433 0,
434 35,
435 80 * channelRateFactor),
436 StandardInfo("802.11ac",
439 serverChannelWidth,
440 dB_u{5},
441 dB_u{50},
442 0,
443 55,
444 120 * channelRateFactor),
445 StandardInfo("802.11p-10MHz",
448 MHz_u{10},
449 dB_u{3},
450 dB_u{27},
451 0,
452 30,
453 60),
454 StandardInfo("802.11p-5MHz",
457 MHz_u{5},
458 dB_u{3},
459 dB_u{27},
460 0,
461 30,
462 60),
463 StandardInfo("802.11ax-6GHz",
466 serverChannelWidth,
467 dB_u{5},
468 dB_u{55},
469 0,
470 60,
471 120 * channelRateFactor),
472 StandardInfo("802.11ax-5GHz",
475 serverChannelWidth,
476 dB_u{5},
477 dB_u{55},
478 0,
479 60,
480 120 * channelRateFactor),
481 StandardInfo("802.11ax-2.4GHz",
484 serverChannelWidth,
485 dB_u{5},
486 dB_u{55},
487 0,
488 60,
489 120 * channelRateFactor),
490 StandardInfo("802.11be-6GHz",
493 serverChannelWidth,
494 5,
495 55,
496 0,
497 60,
498 120 * channelRateFactor),
499 StandardInfo("802.11be-5GHz",
502 serverChannelWidth,
503 5,
504 55,
505 0,
506 60,
507 120 * channelRateFactor),
508 StandardInfo("802.11be-2.4GHz",
511 serverChannelWidth,
512 5,
513 55,
514 0,
515 60,
516 120 * channelRateFactor),
517 };
518
519 clientStandards = {
520 StandardInfo("802.11a",
523 MHz_u{20},
524 dB_u{3},
525 dB_u{27},
526 0,
527 30,
528 60),
529 StandardInfo("802.11b",
532 MHz_u{22},
533 dB_u{-5},
534 dB_u{11},
535 -6,
536 15,
537 15),
538 StandardInfo("802.11g",
541 MHz_u{20},
542 dB_u{-5},
543 dB_u{27},
544 -6,
545 30,
546 60),
547 StandardInfo("802.11n-5GHz",
550 clientChannelWidth,
551 dB_u{3},
552 dB_u{30},
553 0,
554 35,
555 80 * channelRateFactor),
556 StandardInfo("802.11n-2.4GHz",
559 clientChannelWidth,
560 dB_u{3},
561 dB_u{30},
562 0,
563 35,
564 80 * channelRateFactor),
565 StandardInfo("802.11ac",
568 clientChannelWidth,
569 dB_u{5},
570 dB_u{50},
571 0,
572 55,
573 120 * channelRateFactor),
574 StandardInfo("802.11p-10MHz",
577 MHz_u{10},
578 dB_u{3},
579 dB_u{27},
580 0,
581 30,
582 60),
583 StandardInfo("802.11p-5MHz",
586 MHz_u{5},
587 dB_u{3},
588 dB_u{27},
589 0,
590 30,
591 60),
592 StandardInfo("802.11ax-6GHz",
595 clientChannelWidth,
596 dB_u{5},
597 dB_u{55},
598 0,
599 60,
600 160 * channelRateFactor),
601 StandardInfo("802.11ax-5GHz",
604 clientChannelWidth,
605 dB_u{5},
606 dB_u{55},
607 0,
608 60,
609 160 * channelRateFactor),
610 StandardInfo("802.11ax-2.4GHz",
613 clientChannelWidth,
614 dB_u{5},
615 dB_u{55},
616 0,
617 60,
618 160 * channelRateFactor),
619 StandardInfo("802.11be-6GHz",
622 clientChannelWidth,
623 5,
624 55,
625 0,
626 60,
627 160 * channelRateFactor),
628 StandardInfo("802.11be-5GHz",
631 clientChannelWidth,
632 5,
633 55,
634 0,
635 60,
636 160 * channelRateFactor),
637 StandardInfo("802.11be-2.4GHz",
640 clientChannelWidth,
641 5,
642 55,
643 0,
644 60,
645 160 * channelRateFactor),
646 };
647
648 for (std::vector<StandardInfo>::size_type i = 0; i != serverStandards.size(); i++)
649 {
650 if (standard == serverStandards[i].m_name)
651 {
652 serverSelectedStandard = serverStandards[i];
653 }
654 }
655 for (std::vector<StandardInfo>::size_type i = 0; i != clientStandards.size(); i++)
656 {
657 if (standard == clientStandards[i].m_name)
658 {
659 clientSelectedStandard = clientStandards[i];
660 }
661 }
662
663 NS_ABORT_MSG_IF(serverSelectedStandard.m_name == "none",
664 "Standard " << standard << " not found");
665 NS_ABORT_MSG_IF(clientSelectedStandard.m_name == "none",
666 "Standard " << standard << " not found");
667 std::cout << "Testing " << serverSelectedStandard.m_name << " with " << wifiManager << " ..."
668 << std::endl;
669 NS_ABORT_MSG_IF(clientSelectedStandard.m_snrLow >= clientSelectedStandard.m_snrHigh,
670 "SNR values in wrong order");
671 steps = static_cast<uint32_t>(std::abs(static_cast<double>(clientSelectedStandard.m_snrHigh -
672 clientSelectedStandard.m_snrLow) /
673 stepSize) +
674 1);
675 NS_LOG_DEBUG("Using " << steps << " steps for SNR range " << clientSelectedStandard.m_snrLow
676 << ":" << clientSelectedStandard.m_snrHigh);
677 Ptr<Node> clientNode = CreateObject<Node>();
678 Ptr<Node> serverNode = CreateObject<Node>();
679
680 std::string plotName = "wifi-manager-example-";
681 std::string dataName = "wifi-manager-example-";
682 plotName += wifiManager;
683 dataName += wifiManager;
684 plotName += "-";
685 dataName += "-";
686 plotName += standard;
687 dataName += standard;
688 if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz" || standard == "802.11ac" ||
689 standard == "802.11ax-6GHz" || standard == "802.11ax-5GHz" || standard == "802.11ax-2.4GHz")
690 {
691 plotName += "-server_";
692 dataName += "-server_";
693 std::ostringstream oss;
694 oss << serverChannelWidth << "MHz_" << serverShortGuardInterval << "ns_" << serverNss
695 << "SS";
696 plotName += oss.str();
697 dataName += oss.str();
698 plotName += "-client_";
699 dataName += "-client_";
700 oss.str("");
701 oss << clientChannelWidth << "MHz_" << clientShortGuardInterval << "ns_" << clientNss
702 << "SS";
703 plotName += oss.str();
704 dataName += oss.str();
705 }
706 plotName += ".eps";
707 dataName += ".plt";
708 std::ofstream outfile(dataName);
709 Gnuplot gnuplot = Gnuplot(plotName);
710
711 Config::SetDefault("ns3::WifiMac::FrameRetryLimit", UintegerValue(maxRetryCount));
712 Config::SetDefault("ns3::MinstrelWifiManager::PrintStats", BooleanValue(true));
713 Config::SetDefault("ns3::MinstrelWifiManager::PrintSamples", BooleanValue(true));
714 Config::SetDefault("ns3::MinstrelHtWifiManager::PrintStats", BooleanValue(true));
715 // Disable the default noise figure of 7 dBm in WifiPhy; the calculations
716 // of SNR below assume that the only noise is thermal noise
717 Config::SetDefault("ns3::WifiPhy::RxNoiseFigure", DoubleValue(0));
718
719 // By default, the CCA sensitivity is -82 dBm, meaning if the RSS is
720 // below this value, the receiver will reject the Wi-Fi frame.
721 // However, we want to probe the error model down to low SNR values,
722 // and we have disabled the noise figure, so the noise level in 20 MHz
723 // will be about -101 dBm. Therefore, lower the CCA sensitivity to a
724 // value that disables it (e.g. -110 dBm)
725 Config::SetDefault("ns3::WifiPhy::CcaSensitivity", DoubleValue(-110));
726
728 wifi.SetStandard(serverSelectedStandard.m_standard);
729 YansWifiPhyHelper wifiPhy;
730 // Disable the preamble detection model for the same reason that we
731 // disabled CCA sensitivity above-- we want to enable reception at low SNR
733
737 wifiChannel->SetPropagationDelayModel(delayModel);
739 wifiChannel->SetPropagationLossModel(rssLossModel);
740 wifiPhy.SetChannel(wifiChannel);
741
742 wifi.SetRemoteStationManager("ns3::" + wifiManager + "WifiManager",
743 "RtsCtsThreshold",
744 UintegerValue(rtsThreshold));
745
746 NetDeviceContainer serverDevice;
747 NetDeviceContainer clientDevice;
748
751 ';'>
752 channelValue;
753
754 WifiMacHelper wifiMac;
755 if (infrastructure)
756 {
757 Ssid ssid = Ssid("ns-3-ssid");
758 wifiMac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
759 channelValue.Set(WifiPhy::ChannelSegments{
760 {0, serverSelectedStandard.m_width, serverSelectedStandard.m_band, 0}});
761 wifiPhy.Set("ChannelSettings", channelValue);
762 serverDevice = wifi.Install(wifiPhy, wifiMac, serverNode);
763
764 wifiMac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
765 channelValue.Set(WifiPhy::ChannelSegments{
766 {0, clientSelectedStandard.m_width, clientSelectedStandard.m_band, 0}});
767 wifiPhy.Set("ChannelSettings", channelValue);
768 clientDevice = wifi.Install(wifiPhy, wifiMac, clientNode);
769 }
770 else
771 {
772 wifiMac.SetType("ns3::AdhocWifiMac");
773 channelValue.Set(WifiPhy::ChannelSegments{
774 {0, serverSelectedStandard.m_width, serverSelectedStandard.m_band, 0}});
775 wifiPhy.Set("ChannelSettings", channelValue);
776 serverDevice = wifi.Install(wifiPhy, wifiMac, serverNode);
777
778 channelValue.Set(WifiPhy::ChannelSegments{
779 {0, clientSelectedStandard.m_width, clientSelectedStandard.m_band, 0}});
780 wifiPhy.Set("ChannelSettings", channelValue);
781 clientDevice = wifi.Install(wifiPhy, wifiMac, clientNode);
782 }
783
784 WifiHelper::AssignStreams(serverDevice, 100);
785 WifiHelper::AssignStreams(clientDevice, 200);
786
787 Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
788 UintegerValue(maxAmpduSize));
789
791 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager +
792 "WifiManager/Rate",
794
795 // Configure the mobility.
798 // Initial position of AP and STA
799 positionAlloc->Add(Vector(ap1_x, ap1_y, 0.0));
800 NS_LOG_INFO("Setting initial AP position to " << Vector(ap1_x, ap1_y, 0.0));
801 positionAlloc->Add(Vector(sta1_x, sta1_y, 0.0));
802 NS_LOG_INFO("Setting initial STA position to " << Vector(sta1_x, sta1_y, 0.0));
803 mobility.SetPositionAllocator(positionAlloc);
804 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
805 mobility.Install(clientNode);
806 mobility.Install(serverNode);
807
808 Gnuplot2dDataset rateDataset(clientSelectedStandard.m_name + std::string("-rate selected"));
809 Gnuplot2dDataset actualDataset(clientSelectedStandard.m_name + std::string("-observed"));
810 Step step;
811 step.stepSize = stepSize;
812 step.stepTime = stepTime;
813
814 // Perform post-install configuration from defaults for channel width,
815 // guard interval, and nss, if necessary
816 // Obtain pointer to the WifiPhy
817 Ptr<NetDevice> ndClient = clientDevice.Get(0);
818 Ptr<NetDevice> ndServer = serverDevice.Get(0);
819 Ptr<WifiNetDevice> wndClient = ndClient->GetObject<WifiNetDevice>();
820 Ptr<WifiNetDevice> wndServer = ndServer->GetObject<WifiNetDevice>();
821 Ptr<WifiPhy> wifiPhyPtrClient = wndClient->GetPhy();
822 Ptr<WifiPhy> wifiPhyPtrServer = wndServer->GetPhy();
823 auto t_clientNss = static_cast<uint8_t>(clientNss);
824 auto t_serverNss = static_cast<uint8_t>(serverNss);
825 wifiPhyPtrClient->SetNumberOfAntennas(t_clientNss);
826 wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams(t_clientNss);
827 wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams(t_clientNss);
828 wifiPhyPtrServer->SetNumberOfAntennas(t_serverNss);
829 wifiPhyPtrServer->SetMaxSupportedTxSpatialStreams(t_serverNss);
830 wifiPhyPtrServer->SetMaxSupportedRxSpatialStreams(t_serverNss);
831 // Only set the guard interval for HT and VHT modes
832 if (serverSelectedStandard.m_name == "802.11n-5GHz" ||
833 serverSelectedStandard.m_name == "802.11n-2.4GHz" ||
834 serverSelectedStandard.m_name == "802.11ac")
835 {
836 Ptr<HtConfiguration> clientHtConfiguration = wndClient->GetHtConfiguration();
837 clientHtConfiguration->m_sgiSupported = (clientShortGuardInterval == 400);
838 Ptr<HtConfiguration> serverHtConfiguration = wndServer->GetHtConfiguration();
839 serverHtConfiguration->m_sgiSupported = (serverShortGuardInterval == 400);
840 }
841 else if (serverSelectedStandard.m_name == "802.11ax-6GHz" ||
842 serverSelectedStandard.m_name == "802.11ax-5GHz" ||
843 serverSelectedStandard.m_name == "802.11ax-2.4GHz" ||
844 serverSelectedStandard.m_name == "802.11be-6GHz" ||
845 serverSelectedStandard.m_name == "802.11be-5GHz" ||
846 serverSelectedStandard.m_name == "802.11be-2.4GHz")
847 {
848 wndServer->GetHeConfiguration()->SetGuardInterval(NanoSeconds(serverShortGuardInterval));
849 wndClient->GetHeConfiguration()->SetGuardInterval(NanoSeconds(clientShortGuardInterval));
850 }
851
852 // Configure signal and noise, and schedule first iteration
853 const auto BOLTZMANN = 1.3803e-23;
854 const dBm_per_Hz_u noiseDensity = WToDbm(BOLTZMANN * 290); // 290K @ 20 MHz
855 const dBm_u noise = noiseDensity + (10 * log10(clientSelectedStandard.m_width * 1000000));
856
857 NS_LOG_DEBUG("Channel width " << wifiPhyPtrClient->GetChannelWidth() << " noise " << noise);
858 NS_LOG_DEBUG("NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams());
859
860 const dBm_u rssCurrent = (clientSelectedStandard.m_snrHigh + noise);
861 rssLossModel->SetRss(rssCurrent);
862 NS_LOG_INFO("Setting initial Rss to " << rssCurrent);
863 // Move the STA by stepsSize meters every stepTime seconds
864 Simulator::Schedule(Seconds(0.5 + stepTime),
866 rssLossModel,
867 step,
868 rssCurrent,
869 noise,
870 rateDataset,
871 actualDataset);
872
873 PacketSocketHelper packetSocketHelper;
874 packetSocketHelper.Install(serverNode);
875 packetSocketHelper.Install(clientNode);
876
877 PacketSocketAddress socketAddr;
878 socketAddr.SetSingleDevice(serverDevice.Get(0)->GetIfIndex());
879 if (broadcast)
880 {
881 socketAddr.SetPhysicalAddress(serverDevice.Get(0)->GetBroadcast());
882 }
883 else
884 {
885 socketAddr.SetPhysicalAddress(serverDevice.Get(0)->GetAddress());
886 }
887 // Arbitrary protocol type.
888 // Note: PacketSocket doesn't have any L4 multiplexing or demultiplexing
889 // The only mux/demux is based on the protocol field
890 socketAddr.SetProtocol(1);
891
893 client->SetRemote(socketAddr);
894 client->SetStartTime(Seconds(0.5)); // allow simulation warmup
895 client->SetAttribute("MaxPackets", UintegerValue(0)); // unlimited
896 client->SetAttribute("PacketSize", UintegerValue(packetSize));
897
898 // Set a maximum rate 10% above the yMax specified for the selected standard
899 double rate = clientSelectedStandard.m_yMax * 1e6 * 1.10;
900 double clientInterval = static_cast<double>(packetSize) * 8 / rate;
901 NS_LOG_DEBUG("Setting interval to " << clientInterval << " sec for rate of " << rate
902 << " bits/sec");
903
904 client->SetAttribute("Interval", TimeValue(Seconds(clientInterval)));
905 clientNode->AddApplication(client);
906
908 server->SetLocal(socketAddr);
909 server->TraceConnectWithoutContext("Rx", MakeCallback(&PacketRx));
910 serverNode->AddApplication(server);
911
912 Simulator::Stop(Seconds((steps + 1) * stepTime));
914
915 if (serverSelectedStandard.m_standard >= WIFI_STANDARD_80211n)
916 {
917 NS_ABORT_MSG_UNLESS(wndClient->GetMac()->GetBaAgreementEstablishedAsOriginator(
918 wndServer->GetMac()->GetAddress(),
919 0),
920 "Expected BA agreement established for standard "
921 << serverSelectedStandard.m_standard);
922 }
923
925
926 gnuplot.AddDataset(rateDataset);
927 gnuplot.AddDataset(actualDataset);
928
929 std::ostringstream xMinStr;
930 std::ostringstream xMaxStr;
931 std::ostringstream yMaxStr;
932 std::string xRangeStr("set xrange [");
933 xMinStr << clientSelectedStandard.m_xMin;
934 xRangeStr.append(xMinStr.str());
935 xRangeStr.append(":");
936 xMaxStr << clientSelectedStandard.m_xMax;
937 xRangeStr.append(xMaxStr.str());
938 xRangeStr.append("]");
939 std::string yRangeStr("set yrange [0:");
940 yMaxStr << clientSelectedStandard.m_yMax;
941 yRangeStr.append(yMaxStr.str());
942 yRangeStr.append("]");
943
944 std::string title("Results for ");
945 title.append(standard);
946 title.append(" with ");
947 title.append(wifiManager);
948 title.append("\\n");
949 if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz" || standard == "802.11ac" ||
950 standard == "802.11ax-6GHz" || standard == "802.11ax-5GHz" ||
951 standard == "802.11ax-2.4GHz" || standard == "802.11be-6GHz" ||
952 standard == "802.11be-5GHz" || standard == "802.11be-2.4GHz")
953 {
954 std::ostringstream serverGiStrStr;
955 std::ostringstream serverWidthStrStr;
956 std::ostringstream serverNssStrStr;
957 title.append("server: width=");
958 serverWidthStrStr << serverSelectedStandard.m_width;
959 title.append(serverWidthStrStr.str());
960 title.append("MHz");
961 title.append(" GI=");
962 serverGiStrStr << serverShortGuardInterval;
963 title.append(serverGiStrStr.str());
964 title.append("ns");
965 title.append(" nss=");
966 serverNssStrStr << serverNss;
967 title.append(serverNssStrStr.str());
968 title.append("\\n");
969 std::ostringstream clientGiStrStr;
970 std::ostringstream clientWidthStrStr;
971 std::ostringstream clientNssStrStr;
972 title.append("client: width=");
973 clientWidthStrStr << clientSelectedStandard.m_width;
974 title.append(clientWidthStrStr.str());
975 title.append("MHz");
976 title.append(" GI=");
977 clientGiStrStr << clientShortGuardInterval;
978 title.append(clientGiStrStr.str());
979 title.append("ns");
980 title.append(" nss=");
981 clientNssStrStr << clientNss;
982 title.append(clientNssStrStr.str());
983 }
984 gnuplot.SetTerminal("postscript eps color enh \"Times-BoldItalic\"");
985 gnuplot.SetLegend("SNR (dB)", "Rate (Mb/s)");
986 gnuplot.SetTitle(title);
987 gnuplot.SetExtra(xRangeStr);
988 gnuplot.AppendExtra(yRangeStr);
989 gnuplot.AppendExtra("set key top left");
990 gnuplot.GenerateOutput(outfile);
991 outfile.close();
992
993 return 0;
994}
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.
AttributeValue implementation for Boolean.
Definition boolean.h:26
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:561
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
AttributeValue implementation for Ssid.
Definition ssid.h:85
@ S
second
Definition nstime.h:105
AttributeValue implementation for Time.
Definition nstime.h:1432
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:943
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:886
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition config.cc:946
void Set(std::string path, const AttributeValue &value)
Definition config.cc:872
#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:1381
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
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_80211be
@ 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:38
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.