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