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