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)",
252 standard);
253 cmd.AddValue("wifiManager",
254 "Set wifi rate manager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, "
255 "MinstrelHt, Onoe, Rraa, ThompsonSampling)",
256 wifiManager);
257 cmd.AddValue("infrastructure", "Use infrastructure instead of adhoc", infrastructure);
258 cmd.Parse(argc, argv);
259
260 // Print out some explanation of what this program does
261 std::cout << std::endl
262 << "This program demonstrates and plots the operation of different " << std::endl;
263 std::cout << "Wi-Fi rate controls on different station configurations," << std::endl;
264 std::cout << "by stepping down the received signal strength across a wide range" << std::endl;
265 std::cout << "and observing the adjustment of the rate." << std::endl;
266 std::cout << "Run 'wifi-manager-example --PrintHelp' to show program options." << std::endl
267 << std::endl;
268
269 if (!infrastructure)
270 {
271 NS_ABORT_MSG_IF(serverNss != clientNss,
272 "In ad hoc mode, we assume sender and receiver are similarly configured");
273 }
274
275 if (standard == "802.11b")
276 {
277 if (serverChannelWidth == MHz_u{0})
278 {
280 }
281 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{22},
282 "Invalid channel width for standard " << standard);
283 NS_ABORT_MSG_IF(serverNss != 1, "Invalid nss for standard " << standard);
284 if (clientChannelWidth == MHz_u{0})
285 {
287 }
288 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{22},
289 "Invalid channel width for standard " << standard);
290 NS_ABORT_MSG_IF(clientNss != 1, "Invalid nss for standard " << standard);
291 }
292 else if (standard == "802.11a" || standard == "802.11g")
293 {
294 if (serverChannelWidth == MHz_u{0})
295 {
297 }
298 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{20},
299 "Invalid channel width for standard " << standard);
300 NS_ABORT_MSG_IF(serverNss != 1, "Invalid nss for standard " << standard);
301 if (clientChannelWidth == MHz_u{0})
302 {
304 }
305 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{20},
306 "Invalid channel width for standard " << standard);
307 NS_ABORT_MSG_IF(clientNss != 1, "Invalid nss for standard " << standard);
308 }
309 else if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz")
310 {
311 WifiPhyBand band =
312 (standard == "802.11n-2.4GHz" ? WIFI_PHY_BAND_2_4GHZ : WIFI_PHY_BAND_5GHZ);
313 if (serverChannelWidth == MHz_u{0})
314 {
315 serverChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211n, band);
316 }
317 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{20} && serverChannelWidth != MHz_u{40},
318 "Invalid channel width for standard " << standard);
319 NS_ABORT_MSG_IF(serverNss == 0 || serverNss > 4,
320 "Invalid nss " << serverNss << " for standard " << standard);
321 if (clientChannelWidth == MHz_u{0})
322 {
323 clientChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211n, band);
324 }
325 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{20} && clientChannelWidth != MHz_u{40},
326 "Invalid channel width for standard " << standard);
327 NS_ABORT_MSG_IF(clientNss == 0 || clientNss > 4,
328 "Invalid nss " << clientNss << " for standard " << standard);
329 }
330 else if (standard == "802.11ac")
331 {
332 if (serverChannelWidth == MHz_u{0})
333 {
335 }
336 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{20} && serverChannelWidth != MHz_u{40} &&
337 serverChannelWidth != MHz_u{80} && serverChannelWidth != MHz_u{160},
338 "Invalid channel width for standard " << standard);
339 NS_ABORT_MSG_IF(serverNss == 0 || serverNss > 4,
340 "Invalid nss " << serverNss << " for standard " << standard);
341 if (clientChannelWidth == MHz_u{0})
342 {
344 }
345 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{20} && clientChannelWidth != MHz_u{40} &&
346 clientChannelWidth != MHz_u{80} && clientChannelWidth != MHz_u{160},
347 "Invalid channel width for standard " << standard);
348 NS_ABORT_MSG_IF(clientNss == 0 || clientNss > 4,
349 "Invalid nss " << clientNss << " for standard " << standard);
350 }
351 else if (standard == "802.11ax-6GHz" || standard == "802.11ax-5GHz" ||
352 standard == "802.11ax-2.4GHz")
353 {
354 WifiPhyBand band = (standard == "802.11ax-2.4GHz" ? WIFI_PHY_BAND_2_4GHZ
355 : standard == "802.11ax-6GHz" ? WIFI_PHY_BAND_6GHZ
357 if (serverChannelWidth == MHz_u{0})
358 {
359 serverChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211ax, band);
360 }
361 NS_ABORT_MSG_IF(serverChannelWidth != MHz_u{20} && serverChannelWidth != MHz_u{40} &&
362 serverChannelWidth != MHz_u{80} && serverChannelWidth != MHz_u{160},
363 "Invalid channel width for standard " << standard);
364 NS_ABORT_MSG_IF(serverNss == 0 || serverNss > 4,
365 "Invalid nss " << serverNss << " for standard " << standard);
366 if (clientChannelWidth == MHz_u{0})
367 {
368 clientChannelWidth = GetDefaultChannelWidth(WIFI_STANDARD_80211ax, band);
369 }
370 NS_ABORT_MSG_IF(clientChannelWidth != MHz_u{20} && clientChannelWidth != MHz_u{40} &&
371 clientChannelWidth != MHz_u{80} && clientChannelWidth != MHz_u{160},
372 "Invalid channel width for standard " << standard);
373 NS_ABORT_MSG_IF(clientNss == 0 || clientNss > 4,
374 "Invalid nss " << clientNss << " for standard " << standard);
375 }
376
377 // As channel width increases, scale up plot's yRange value
378 uint32_t channelRateFactor = std::max(clientChannelWidth, serverChannelWidth) / MHz_u{20};
379 channelRateFactor = channelRateFactor * std::max(clientNss, serverNss);
380
381 // The first number is channel width, second is minimum SNR, third is maximum
382 // SNR, fourth and fifth provide xrange axis limits, and sixth the yaxis
383 // maximum
384 serverStandards = {
385 StandardInfo("802.11a",
388 MHz_u{20},
389 dB_u{3},
390 dB_u{27},
391 0,
392 30,
393 60),
394 StandardInfo("802.11b",
397 MHz_u{22},
398 dB_u{-5},
399 dB_u{11},
400 -6,
401 15,
402 15),
403 StandardInfo("802.11g",
406 MHz_u{20},
407 dB_u{-5},
408 dB_u{27},
409 -6,
410 30,
411 60),
412 StandardInfo("802.11n-5GHz",
415 serverChannelWidth,
416 dB_u{3},
417 dB_u{30},
418 0,
419 35,
420 80 * channelRateFactor),
421 StandardInfo("802.11n-2.4GHz",
424 serverChannelWidth,
425 dB_u{3},
426 dB_u{30},
427 0,
428 35,
429 80 * channelRateFactor),
430 StandardInfo("802.11ac",
433 serverChannelWidth,
434 dB_u{5},
435 dB_u{50},
436 0,
437 55,
438 120 * channelRateFactor),
439 StandardInfo("802.11p-10MHz",
442 MHz_u{10},
443 dB_u{3},
444 dB_u{27},
445 0,
446 30,
447 60),
448 StandardInfo("802.11p-5MHz",
451 MHz_u{5},
452 dB_u{3},
453 dB_u{27},
454 0,
455 30,
456 60),
457 StandardInfo("802.11ax-6GHz",
460 serverChannelWidth,
461 dB_u{5},
462 dB_u{55},
463 0,
464 60,
465 120 * channelRateFactor),
466 StandardInfo("802.11ax-5GHz",
469 serverChannelWidth,
470 dB_u{5},
471 dB_u{55},
472 0,
473 60,
474 120 * channelRateFactor),
475 StandardInfo("802.11ax-2.4GHz",
478 serverChannelWidth,
479 dB_u{5},
480 dB_u{55},
481 0,
482 60,
483 120 * channelRateFactor),
484 };
485
486 clientStandards = {
487 StandardInfo("802.11a",
490 MHz_u{20},
491 dB_u{3},
492 dB_u{27},
493 0,
494 30,
495 60),
496 StandardInfo("802.11b",
499 MHz_u{22},
500 dB_u{-5},
501 dB_u{11},
502 -6,
503 15,
504 15),
505 StandardInfo("802.11g",
508 MHz_u{20},
509 dB_u{-5},
510 dB_u{27},
511 -6,
512 30,
513 60),
514 StandardInfo("802.11n-5GHz",
517 clientChannelWidth,
518 dB_u{3},
519 dB_u{30},
520 0,
521 35,
522 80 * channelRateFactor),
523 StandardInfo("802.11n-2.4GHz",
526 clientChannelWidth,
527 dB_u{3},
528 dB_u{30},
529 0,
530 35,
531 80 * channelRateFactor),
532 StandardInfo("802.11ac",
535 clientChannelWidth,
536 dB_u{5},
537 dB_u{50},
538 0,
539 55,
540 120 * channelRateFactor),
541 StandardInfo("802.11p-10MHz",
544 MHz_u{10},
545 dB_u{3},
546 dB_u{27},
547 0,
548 30,
549 60),
550 StandardInfo("802.11p-5MHz",
553 MHz_u{5},
554 dB_u{3},
555 dB_u{27},
556 0,
557 30,
558 60),
559 StandardInfo("802.11ax-6GHz",
562 clientChannelWidth,
563 dB_u{5},
564 dB_u{55},
565 0,
566 60,
567 160 * channelRateFactor),
568 StandardInfo("802.11ax-5GHz",
571 clientChannelWidth,
572 dB_u{5},
573 dB_u{55},
574 0,
575 60,
576 160 * channelRateFactor),
577 StandardInfo("802.11ax-2.4GHz",
580 clientChannelWidth,
581 dB_u{5},
582 dB_u{55},
583 0,
584 60,
585 160 * channelRateFactor),
586 };
587
588 for (std::vector<StandardInfo>::size_type i = 0; i != serverStandards.size(); i++)
589 {
590 if (standard == serverStandards[i].m_name)
591 {
592 serverSelectedStandard = serverStandards[i];
593 }
594 }
595 for (std::vector<StandardInfo>::size_type i = 0; i != clientStandards.size(); i++)
596 {
597 if (standard == clientStandards[i].m_name)
598 {
599 clientSelectedStandard = clientStandards[i];
600 }
601 }
602
603 NS_ABORT_MSG_IF(serverSelectedStandard.m_name == "none",
604 "Standard " << standard << " not found");
605 NS_ABORT_MSG_IF(clientSelectedStandard.m_name == "none",
606 "Standard " << standard << " not found");
607 std::cout << "Testing " << serverSelectedStandard.m_name << " with " << wifiManager << " ..."
608 << std::endl;
609 NS_ABORT_MSG_IF(clientSelectedStandard.m_snrLow >= clientSelectedStandard.m_snrHigh,
610 "SNR values in wrong order");
611 steps = static_cast<uint32_t>(std::abs(static_cast<double>(clientSelectedStandard.m_snrHigh -
612 clientSelectedStandard.m_snrLow) /
613 stepSize) +
614 1);
615 NS_LOG_DEBUG("Using " << steps << " steps for SNR range " << clientSelectedStandard.m_snrLow
616 << ":" << clientSelectedStandard.m_snrHigh);
617 Ptr<Node> clientNode = CreateObject<Node>();
618 Ptr<Node> serverNode = CreateObject<Node>();
619
620 std::string plotName = "wifi-manager-example-";
621 std::string dataName = "wifi-manager-example-";
622 plotName += wifiManager;
623 dataName += wifiManager;
624 plotName += "-";
625 dataName += "-";
626 plotName += standard;
627 dataName += standard;
628 if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz" || standard == "802.11ac" ||
629 standard == "802.11ax-6GHz" || standard == "802.11ax-5GHz" || standard == "802.11ax-2.4GHz")
630 {
631 plotName += "-server_";
632 dataName += "-server_";
633 std::ostringstream oss;
634 oss << serverChannelWidth << "MHz_" << serverShortGuardInterval << "ns_" << serverNss
635 << "SS";
636 plotName += oss.str();
637 dataName += oss.str();
638 plotName += "-client_";
639 dataName += "-client_";
640 oss.str("");
641 oss << clientChannelWidth << "MHz_" << clientShortGuardInterval << "ns_" << clientNss
642 << "SS";
643 plotName += oss.str();
644 dataName += oss.str();
645 }
646 plotName += ".eps";
647 dataName += ".plt";
648 std::ofstream outfile(dataName);
649 Gnuplot gnuplot = Gnuplot(plotName);
650
651 Config::SetDefault("ns3::WifiMac::FrameRetryLimit", UintegerValue(maxRetryCount));
652 Config::SetDefault("ns3::MinstrelWifiManager::PrintStats", BooleanValue(true));
653 Config::SetDefault("ns3::MinstrelWifiManager::PrintSamples", BooleanValue(true));
654 Config::SetDefault("ns3::MinstrelHtWifiManager::PrintStats", BooleanValue(true));
655 // Disable the default noise figure of 7 dBm in WifiPhy; the calculations
656 // of SNR below assume that the only noise is thermal noise
657 Config::SetDefault("ns3::WifiPhy::RxNoiseFigure", DoubleValue(0));
658
659 // By default, the CCA sensitivity is -82 dBm, meaning if the RSS is
660 // below this value, the receiver will reject the Wi-Fi frame.
661 // However, we want to probe the error model down to low SNR values,
662 // and we have disabled the noise figure, so the noise level in 20 MHz
663 // will be about -101 dBm. Therefore, lower the CCA sensitivity to a
664 // value that disables it (e.g. -110 dBm)
665 Config::SetDefault("ns3::WifiPhy::CcaSensitivity", DoubleValue(-110));
666
668 wifi.SetStandard(serverSelectedStandard.m_standard);
669 YansWifiPhyHelper wifiPhy;
670 // Disable the preamble detection model for the same reason that we
671 // disabled CCA sensitivity above-- we want to enable reception at low SNR
673
677 wifiChannel->SetPropagationDelayModel(delayModel);
679 wifiChannel->SetPropagationLossModel(rssLossModel);
680 wifiPhy.SetChannel(wifiChannel);
681
682 wifi.SetRemoteStationManager("ns3::" + wifiManager + "WifiManager",
683 "RtsCtsThreshold",
684 UintegerValue(rtsThreshold));
685
686 NetDeviceContainer serverDevice;
687 NetDeviceContainer clientDevice;
688
691 ';'>
692 channelValue;
693
694 WifiMacHelper wifiMac;
695 if (infrastructure)
696 {
697 Ssid ssid = Ssid("ns-3-ssid");
698 wifiMac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
699 channelValue.Set(WifiPhy::ChannelSegments{
700 {0, serverSelectedStandard.m_width, serverSelectedStandard.m_band, 0}});
701 wifiPhy.Set("ChannelSettings", channelValue);
702 serverDevice = wifi.Install(wifiPhy, wifiMac, serverNode);
703
704 wifiMac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
705 channelValue.Set(WifiPhy::ChannelSegments{
706 {0, clientSelectedStandard.m_width, clientSelectedStandard.m_band, 0}});
707 wifiPhy.Set("ChannelSettings", channelValue);
708 clientDevice = wifi.Install(wifiPhy, wifiMac, clientNode);
709 }
710 else
711 {
712 wifiMac.SetType("ns3::AdhocWifiMac");
713 channelValue.Set(WifiPhy::ChannelSegments{
714 {0, serverSelectedStandard.m_width, serverSelectedStandard.m_band, 0}});
715 wifiPhy.Set("ChannelSettings", channelValue);
716 serverDevice = wifi.Install(wifiPhy, wifiMac, serverNode);
717
718 channelValue.Set(WifiPhy::ChannelSegments{
719 {0, clientSelectedStandard.m_width, clientSelectedStandard.m_band, 0}});
720 wifiPhy.Set("ChannelSettings", channelValue);
721 clientDevice = wifi.Install(wifiPhy, wifiMac, clientNode);
722 }
723
724 WifiHelper::AssignStreams(serverDevice, 100);
725 WifiHelper::AssignStreams(clientDevice, 200);
726
727 Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
728 UintegerValue(maxAmpduSize));
729
731 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager +
732 "WifiManager/Rate",
734
735 // Configure the mobility.
738 // Initial position of AP and STA
739 positionAlloc->Add(Vector(ap1_x, ap1_y, 0.0));
740 NS_LOG_INFO("Setting initial AP position to " << Vector(ap1_x, ap1_y, 0.0));
741 positionAlloc->Add(Vector(sta1_x, sta1_y, 0.0));
742 NS_LOG_INFO("Setting initial STA position to " << Vector(sta1_x, sta1_y, 0.0));
743 mobility.SetPositionAllocator(positionAlloc);
744 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
745 mobility.Install(clientNode);
746 mobility.Install(serverNode);
747
748 Gnuplot2dDataset rateDataset(clientSelectedStandard.m_name + std::string("-rate selected"));
749 Gnuplot2dDataset actualDataset(clientSelectedStandard.m_name + std::string("-observed"));
750 Step step;
751 step.stepSize = stepSize;
752 step.stepTime = stepTime;
753
754 // Perform post-install configuration from defaults for channel width,
755 // guard interval, and nss, if necessary
756 // Obtain pointer to the WifiPhy
757 Ptr<NetDevice> ndClient = clientDevice.Get(0);
758 Ptr<NetDevice> ndServer = serverDevice.Get(0);
759 Ptr<WifiNetDevice> wndClient = ndClient->GetObject<WifiNetDevice>();
760 Ptr<WifiNetDevice> wndServer = ndServer->GetObject<WifiNetDevice>();
761 Ptr<WifiPhy> wifiPhyPtrClient = wndClient->GetPhy();
762 Ptr<WifiPhy> wifiPhyPtrServer = wndServer->GetPhy();
763 auto t_clientNss = static_cast<uint8_t>(clientNss);
764 auto t_serverNss = static_cast<uint8_t>(serverNss);
765 wifiPhyPtrClient->SetNumberOfAntennas(t_clientNss);
766 wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams(t_clientNss);
767 wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams(t_clientNss);
768 wifiPhyPtrServer->SetNumberOfAntennas(t_serverNss);
769 wifiPhyPtrServer->SetMaxSupportedTxSpatialStreams(t_serverNss);
770 wifiPhyPtrServer->SetMaxSupportedRxSpatialStreams(t_serverNss);
771 // Only set the guard interval for HT and VHT modes
772 if (serverSelectedStandard.m_name == "802.11n-5GHz" ||
773 serverSelectedStandard.m_name == "802.11n-2.4GHz" ||
774 serverSelectedStandard.m_name == "802.11ac")
775 {
776 Ptr<HtConfiguration> clientHtConfiguration = wndClient->GetHtConfiguration();
777 clientHtConfiguration->m_sgiSupported = (clientShortGuardInterval == 400);
778 Ptr<HtConfiguration> serverHtConfiguration = wndServer->GetHtConfiguration();
779 serverHtConfiguration->m_sgiSupported = (serverShortGuardInterval == 400);
780 }
781 else if (serverSelectedStandard.m_name == "802.11ax-6GHz" ||
782 serverSelectedStandard.m_name == "802.11ax-5GHz" ||
783 serverSelectedStandard.m_name == "802.11ax-2.4GHz")
784 {
785 wndServer->GetHeConfiguration()->SetGuardInterval(NanoSeconds(serverShortGuardInterval));
786 wndClient->GetHeConfiguration()->SetGuardInterval(NanoSeconds(clientShortGuardInterval));
787 }
788
789 // Configure signal and noise, and schedule first iteration
790 const auto BOLTZMANN = 1.3803e-23;
791 const dBm_per_Hz_u noiseDensity = WToDbm(BOLTZMANN * 290); // 290K @ 20 MHz
792 const dBm_u noise = noiseDensity + (10 * log10(clientSelectedStandard.m_width * 1000000));
793
794 NS_LOG_DEBUG("Channel width " << wifiPhyPtrClient->GetChannelWidth() << " noise " << noise);
795 NS_LOG_DEBUG("NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams());
796
797 const dBm_u rssCurrent = (clientSelectedStandard.m_snrHigh + noise);
798 rssLossModel->SetRss(rssCurrent);
799 NS_LOG_INFO("Setting initial Rss to " << rssCurrent);
800 // Move the STA by stepsSize meters every stepTime seconds
801 Simulator::Schedule(Seconds(0.5 + stepTime),
803 rssLossModel,
804 step,
805 rssCurrent,
806 noise,
807 rateDataset,
808 actualDataset);
809
810 PacketSocketHelper packetSocketHelper;
811 packetSocketHelper.Install(serverNode);
812 packetSocketHelper.Install(clientNode);
813
814 PacketSocketAddress socketAddr;
815 socketAddr.SetSingleDevice(serverDevice.Get(0)->GetIfIndex());
816 if (broadcast)
817 {
818 socketAddr.SetPhysicalAddress(serverDevice.Get(0)->GetBroadcast());
819 }
820 else
821 {
822 socketAddr.SetPhysicalAddress(serverDevice.Get(0)->GetAddress());
823 }
824 // Arbitrary protocol type.
825 // Note: PacketSocket doesn't have any L4 multiplexing or demultiplexing
826 // The only mux/demux is based on the protocol field
827 socketAddr.SetProtocol(1);
828
830 client->SetRemote(socketAddr);
831 client->SetStartTime(Seconds(0.5)); // allow simulation warmup
832 client->SetAttribute("MaxPackets", UintegerValue(0)); // unlimited
833 client->SetAttribute("PacketSize", UintegerValue(packetSize));
834
835 // Set a maximum rate 10% above the yMax specified for the selected standard
836 double rate = clientSelectedStandard.m_yMax * 1e6 * 1.10;
837 double clientInterval = static_cast<double>(packetSize) * 8 / rate;
838 NS_LOG_DEBUG("Setting interval to " << clientInterval << " sec for rate of " << rate
839 << " bits/sec");
840
841 client->SetAttribute("Interval", TimeValue(Seconds(clientInterval)));
842 clientNode->AddApplication(client);
843
845 server->SetLocal(socketAddr);
846 server->TraceConnectWithoutContext("Rx", MakeCallback(&PacketRx));
847 serverNode->AddApplication(server);
848
849 Simulator::Stop(Seconds((steps + 1) * stepTime));
851
852 if (serverSelectedStandard.m_standard >= WIFI_STANDARD_80211n)
853 {
854 NS_ABORT_MSG_UNLESS(wndClient->GetMac()->GetBaAgreementEstablishedAsOriginator(
855 wndServer->GetMac()->GetAddress(),
856 0),
857 "Expected BA agreement established for standard "
858 << serverSelectedStandard.m_standard);
859 }
860
862
863 gnuplot.AddDataset(rateDataset);
864 gnuplot.AddDataset(actualDataset);
865
866 std::ostringstream xMinStr;
867 std::ostringstream xMaxStr;
868 std::ostringstream yMaxStr;
869 std::string xRangeStr("set xrange [");
870 xMinStr << clientSelectedStandard.m_xMin;
871 xRangeStr.append(xMinStr.str());
872 xRangeStr.append(":");
873 xMaxStr << clientSelectedStandard.m_xMax;
874 xRangeStr.append(xMaxStr.str());
875 xRangeStr.append("]");
876 std::string yRangeStr("set yrange [0:");
877 yMaxStr << clientSelectedStandard.m_yMax;
878 yRangeStr.append(yMaxStr.str());
879 yRangeStr.append("]");
880
881 std::string title("Results for ");
882 title.append(standard);
883 title.append(" with ");
884 title.append(wifiManager);
885 title.append("\\n");
886 if (standard == "802.11n-5GHz" || standard == "802.11n-2.4GHz" || standard == "802.11ac" ||
887 standard == "802.11ax-6GHz" || standard == "802.11ax-5GHz" || standard == "802.11ax-2.4GHz")
888 {
889 std::ostringstream serverGiStrStr;
890 std::ostringstream serverWidthStrStr;
891 std::ostringstream serverNssStrStr;
892 title.append("server: width=");
893 serverWidthStrStr << serverSelectedStandard.m_width;
894 title.append(serverWidthStrStr.str());
895 title.append("MHz");
896 title.append(" GI=");
897 serverGiStrStr << serverShortGuardInterval;
898 title.append(serverGiStrStr.str());
899 title.append("ns");
900 title.append(" nss=");
901 serverNssStrStr << serverNss;
902 title.append(serverNssStrStr.str());
903 title.append("\\n");
904 std::ostringstream clientGiStrStr;
905 std::ostringstream clientWidthStrStr;
906 std::ostringstream clientNssStrStr;
907 title.append("client: width=");
908 clientWidthStrStr << clientSelectedStandard.m_width;
909 title.append(clientWidthStrStr.str());
910 title.append("MHz");
911 title.append(" GI=");
912 clientGiStrStr << clientShortGuardInterval;
913 title.append(clientGiStrStr.str());
914 title.append("ns");
915 title.append(" nss=");
916 clientNssStrStr << clientNss;
917 title.append(clientNssStrStr.str());
918 }
919 gnuplot.SetTerminal("postscript eps color enh \"Times-BoldItalic\"");
920 gnuplot.SetLegend("SNR (dB)", "Rate (Mb/s)");
921 gnuplot.SetTitle(title);
922 gnuplot.SetExtra(xRangeStr);
923 gnuplot.AppendExtra(yRangeStr);
924 gnuplot.AppendExtra("set key top left");
925 gnuplot.GenerateOutput(outfile);
926 outfile.close();
927
928 return 0;
929}
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: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
AttributeValue implementation for Ssid.
Definition ssid.h:85
@ S
second
Definition nstime.h:105
AttributeValue implementation for Time.
Definition nstime.h:1431
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:936
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:1380
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
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:39
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.