A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-bianchi.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012 The Boeing Company
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Gary Pei <guangyu.pei@boeing.com>
7 *
8 * Updated by Tom Henderson, Rohan Patidar, Hao Yin and Sébastien Deronne
9 */
10
11// This program conducts a Bianchi analysis of a wifi network.
12// Bianchi analysis involves saturating the network and observing how
13// the maximum achievable throughput is governed by the DCF or ECDA
14// channel access mechanisms. This program offers many configurable
15// options, traces, and a validation option; the main output is a Gnuplot
16// plot file plotting throughput vs. number of nodes.
17
18#include "ns3/ampdu-subframe-header.h"
19#include "ns3/application-container.h"
20#include "ns3/boolean.h"
21#include "ns3/command-line.h"
22#include "ns3/config.h"
23#include "ns3/double.h"
24#include "ns3/gnuplot.h"
25#include "ns3/integer.h"
26#include "ns3/log.h"
27#include "ns3/mobility-helper.h"
28#include "ns3/node-list.h"
29#include "ns3/packet-socket-client.h"
30#include "ns3/packet-socket-helper.h"
31#include "ns3/packet-socket-server.h"
32#include "ns3/propagation-delay-model.h"
33#include "ns3/propagation-loss-model.h"
34#include "ns3/queue-size.h"
35#include "ns3/rng-seed-manager.h"
36#include "ns3/ssid.h"
37#include "ns3/string.h"
38#include "ns3/uinteger.h"
39#include "ns3/wifi-mac-header.h"
40#include "ns3/wifi-mac.h"
41#include "ns3/wifi-net-device.h"
42#include "ns3/wifi-phy-rx-trace-helper.h"
43#include "ns3/wifi-tx-stats-helper.h"
44#include "ns3/yans-wifi-helper.h"
45
46#include <fstream>
47#include <iomanip>
48#include <vector>
49
50/**
51 * @file
52 * Example comparing ns-3 to the Bianchi model.
53 *
54 * See the Wi-Fi Module documentation in the Models chapter.
55 */
56
57/// Avoid std::numbers::pi because it's C++20
58#define PI 3.1415926535
59
60NS_LOG_COMPONENT_DEFINE("WifiBianchi");
61
62using namespace ns3;
63
64/** Unnamed namespace, to disambiguate class Experiment. */
65namespace
66{
67
68std::ofstream cwTraceFile; ///< File that traces CW over time
69std::ofstream backoffTraceFile; ///< File that traces backoff over time
70std::ofstream phyTxTraceFile; ///< File that traces PHY transmissions over time
71std::ofstream macTxTraceFile; ///< File that traces MAC transmissions over time
72std::ofstream macRxTraceFile; ///< File that traces MAC receptions over time
73std::ofstream
74 socketSendTraceFile; ///< File that traces packets transmitted by the application over time
75
76std::map<Mac48Address, uint64_t> packetsReceived; ///< Map that stores the total packets received
77 ///< per STA (and addressed to that STA)
78std::map<Mac48Address, uint64_t>
79 bytesReceived; ///< Map that stores the total bytes received per STA (and addressed to that STA)
80std::map<Mac48Address, uint64_t>
81 packetsTransmitted; ///< Map that stores the total packets transmitted per STA
82std::map<Mac48Address, uint64_t>
83 psduFailed; ///< Map that stores the total number of unsuccessfully received PSDUS (for which
84 ///< the PHY header was successfully received) per STA (including PSDUs not
85 ///< addressed to that STA)
86std::map<Mac48Address, uint64_t>
87 psduSucceeded; ///< Map that stores the total number of successfully received PSDUs per STA
88 ///< (including PSDUs not addressed to that STA)
89std::map<Mac48Address, uint64_t> phyHeaderFailed; ///< Map that stores the total number of
90 ///< unsuccessfully received PHY headers per STA
91std::map<Mac48Address, uint64_t>
92 rxEventWhileTxing; ///< Map that stores the number of reception events per STA that occurred
93 ///< while PHY was already transmitting a PPDU
94std::map<Mac48Address, uint64_t>
95 rxEventWhileRxing; ///< Map that stores the number of reception events per STA that occurred
96 ///< while PHY was already receiving a PPDU
97std::map<Mac48Address, uint64_t>
98 rxEventWhileDecodingPreamble; ///< Map that stores the number of reception events per STA that
99 ///< occurred while PHY was already decoding a preamble
100std::map<Mac48Address, uint64_t>
101 rxEventAbortedByTx; ///< Map that stores the number of reception events aborted per STA because
102 ///< the PHY has started to transmit
103
104std::map<Mac48Address, Time>
105 timeFirstReceived; ///< Map that stores the time at which the first packet was received per STA
106 ///< (and the packet is addressed to that STA)
107std::map<Mac48Address, Time>
108 timeLastReceived; ///< Map that stores the time at which the last packet was received per STA
109 ///< (and the packet is addressed to that STA)
110std::map<Mac48Address, Time> timeFirstTransmitted; ///< Map that stores the time at which the first
111 ///< packet was transmitted per STA
112std::map<Mac48Address, Time> timeLastTransmitted; ///< Map that stores the time at which the last
113 ///< packet was transmitted per STA
114
115std::set<uint32_t> associated; ///< Contains the IDs of the STAs that successfully associated to the
116 ///< access point (in infrastructure mode only)
117
118bool tracing = false; ///< Flag to enable/disable generation of tracing files
119uint32_t pktSize = 1500; ///< packet size used for the simulation (in bytes)
120uint8_t maxMpdus = 0; ///< The maximum number of MPDUs in A-MPDUs (0 to disable MPDU aggregation)
121bool useTxHelper = false; ///< Flag to get MPDU statistics with WifiTxStatsHelper
122bool useRxHelper = false; ///< Flag to get PPDU statistics with WifiPhyRxTraceHelper
123
124/// Table of the expected values for EIFS
125std::map<std::string /* mode */,
126 std::map<unsigned int /* number of nodes */, double /* calculated throughput */>>
128 /* 11b */
129 {"DsssRate1Mbps",
130 {
131 {5, 0.8418},
132 {10, 0.7831},
133 {15, 0.7460},
134 {20, 0.7186},
135 {25, 0.6973},
136 {30, 0.6802},
137 {35, 0.6639},
138 {40, 0.6501},
139 {45, 0.6386},
140 {50, 0.6285},
141 }},
142 {"DsssRate2Mbps",
143 {
144 {5, 1.6170},
145 {10, 1.5075},
146 {15, 1.4371},
147 {20, 1.3849},
148 {25, 1.3442},
149 {30, 1.3115},
150 {35, 1.2803},
151 {40, 1.2538},
152 {45, 1.2317},
153 {50, 1.2124},
154 }},
155 {"DsssRate5_5Mbps",
156 {
157 {5, 3.8565},
158 {10, 3.6170},
159 {15, 3.4554},
160 {20, 3.3339},
161 {25, 3.2385},
162 {30, 3.1613},
163 {35, 3.0878},
164 {40, 3.0249},
165 {45, 2.9725},
166 {50, 2.9266},
167 }},
168 {"DsssRate11Mbps",
169 {
170 {5, 6.3821},
171 {10, 6.0269},
172 {15, 5.7718},
173 {20, 5.5765},
174 {25, 5.4217},
175 {30, 5.2958},
176 {35, 5.1755},
177 {40, 5.0722},
178 {45, 4.9860},
179 {50, 4.9103},
180 }},
181 /* 11a */
182 {"OfdmRate6Mbps",
183 {
184 {5, 4.6899},
185 {10, 4.3197},
186 {15, 4.1107},
187 {20, 3.9589},
188 {25, 3.8478},
189 {30, 3.7490},
190 {35, 3.6618},
191 {40, 3.5927},
192 {45, 3.5358},
193 {50, 3.4711},
194 }},
195 {"OfdmRate9Mbps",
196 {
197 {5, 6.8188},
198 {10, 6.2885},
199 {15, 5.9874},
200 {20, 5.7680},
201 {25, 5.6073},
202 {30, 5.4642},
203 {35, 5.3378},
204 {40, 5.2376},
205 {45, 5.1551},
206 {50, 5.0612},
207 }},
208 {"OfdmRate12Mbps",
209 {
210 {5, 8.8972},
211 {10, 8.2154},
212 {15, 7.8259},
213 {20, 7.5415},
214 {25, 7.3329},
215 {30, 7.1469},
216 {35, 6.9825},
217 {40, 6.8521},
218 {45, 6.7447},
219 {50, 6.6225},
220 }},
221 {"OfdmRate18Mbps",
222 {
223 {5, 12.6719},
224 {10, 11.7273},
225 {15, 11.1814},
226 {20, 10.7810},
227 {25, 10.4866},
228 {30, 10.2237},
229 {35, 9.9910},
230 {40, 9.8061},
231 {45, 9.6538},
232 {50, 9.4804},
233 }},
234 {"OfdmRate24Mbps",
235 {
236 {5, 16.0836},
237 {10, 14.9153},
238 {15, 14.2327},
239 {20, 13.7300},
240 {25, 13.3595},
241 {30, 13.0281},
242 {35, 12.7343},
243 {40, 12.5008},
244 {45, 12.3083},
245 {50, 12.0889},
246 }},
247 {"OfdmRate36Mbps",
248 {
249 {5, 22.0092},
250 {10, 20.4836},
251 {15, 19.5743},
252 {20, 18.8997},
253 {25, 18.4002},
254 {30, 17.9524},
255 {35, 17.5545},
256 {40, 17.2377},
257 {45, 16.9760},
258 {50, 16.6777},
259 }},
260 {"OfdmRate48Mbps",
261 {
262 {5, 26.8382},
263 {10, 25.0509},
264 {15, 23.9672},
265 {20, 23.1581},
266 {25, 22.5568},
267 {30, 22.0165},
268 {35, 21.5355},
269 {40, 21.1519},
270 {45, 20.8348},
271 {50, 20.4729},
272 }},
273 {"OfdmRate54Mbps",
274 {
275 {5, 29.2861},
276 {10, 27.3763},
277 {15, 26.2078},
278 {20, 25.3325},
279 {25, 24.6808},
280 {30, 24.0944},
281 {35, 23.5719},
282 {40, 23.1549},
283 {45, 22.8100},
284 {50, 22.4162},
285 }},
286 /* 11g */
287 {"ErpOfdmRate6Mbps",
288 {
289 {5, 4.6899},
290 {10, 4.3197},
291 {15, 4.1107},
292 {20, 3.9589},
293 {25, 3.8478},
294 {30, 3.7490},
295 {35, 3.6618},
296 {40, 3.5927},
297 {45, 3.5358},
298 {50, 3.4711},
299 }},
300 {"ErpOfdmRate9Mbps",
301 {
302 {5, 6.8188},
303 {10, 6.2885},
304 {15, 5.9874},
305 {20, 5.7680},
306 {25, 5.6073},
307 {30, 5.4642},
308 {35, 5.3378},
309 {40, 5.2376},
310 {45, 5.1551},
311 {50, 5.0612},
312 }},
313 {"ErpOfdmRate12Mbps",
314 {
315 {5, 8.8972},
316 {10, 8.2154},
317 {15, 7.8259},
318 {20, 7.5415},
319 {25, 7.3329},
320 {30, 7.1469},
321 {35, 6.9825},
322 {40, 6.8521},
323 {45, 6.7447},
324 {50, 6.6225},
325 }},
326 {"ErpOfdmRate18Mbps",
327 {
328 {5, 12.6719},
329 {10, 11.7273},
330 {15, 11.1814},
331 {20, 10.7810},
332 {25, 10.4866},
333 {30, 10.2237},
334 {35, 9.9910},
335 {40, 9.8061},
336 {45, 9.6538},
337 {50, 9.4804},
338 }},
339 {"ErpOfdmRate24Mbps",
340 {
341 {5, 16.0836},
342 {10, 14.9153},
343 {15, 14.2327},
344 {20, 13.7300},
345 {25, 13.3595},
346 {30, 13.0281},
347 {35, 12.7343},
348 {40, 12.5008},
349 {45, 12.3083},
350 {50, 12.0889},
351 }},
352 {"ErpOfdmRate36Mbps",
353 {
354 {5, 22.0092},
355 {10, 20.4836},
356 {15, 19.5743},
357 {20, 18.8997},
358 {25, 18.4002},
359 {30, 17.9524},
360 {35, 17.5545},
361 {40, 17.2377},
362 {45, 16.9760},
363 {50, 16.6777},
364 }},
365 {"ErpOfdmRate48Mbps",
366 {
367 {5, 26.8382},
368 {10, 25.0509},
369 {15, 23.9672},
370 {20, 23.1581},
371 {25, 22.5568},
372 {30, 22.0165},
373 {35, 21.5355},
374 {40, 21.1519},
375 {45, 20.8348},
376 {50, 20.4729},
377 }},
378 {"ErpOfdmRate54Mbps",
379 {
380 {5, 29.2861},
381 {10, 27.3763},
382 {15, 26.2078},
383 {20, 25.3325},
384 {25, 24.6808},
385 {30, 24.0944},
386 {35, 23.5719},
387 {40, 23.1549},
388 {45, 22.8100},
389 {50, 22.4162},
390 }},
391 /* 11ax, no frame aggregation */
392 {"HeMcs0_20MHz",
393 {
394 {5, 6.3381},
395 {10, 5.8172},
396 {15, 5.5223},
397 {20, 5.3146},
398 {25, 5.1525},
399 {30, 5.0187},
400 {35, 4.9039},
401 {40, 4.8034},
402 {45, 4.7134},
403 {50, 4.6317},
404 }},
405 {"HeMcs1_20MHz",
406 {
407 {5, 11.6580},
408 {10, 10.7369},
409 {15, 10.2068},
410 {20, 9.8309},
411 {25, 9.5365},
412 {30, 9.2930},
413 {35, 9.0837},
414 {40, 8.9001},
415 {45, 8.7355},
416 {50, 8.5860},
417 }},
418 {"HeMcs2_20MHz",
419 {
420 {5, 15.8572},
421 {10, 14.6445},
422 {15, 13.9367},
423 {20, 13.4323},
424 {25, 13.0361},
425 {30, 12.7076},
426 {35, 12.4249},
427 {40, 12.1766},
428 {45, 11.9538},
429 {50, 11.7511},
430 }},
431 {"HeMcs3_20MHz",
432 {
433 {5, 19.7457},
434 {10, 18.2820},
435 {15, 17.4163},
436 {20, 16.7963},
437 {25, 16.3078},
438 {30, 15.9021},
439 {35, 15.5524},
440 {40, 15.2449},
441 {45, 14.9687},
442 {50, 14.7173},
443 }},
444 {"HeMcs4_20MHz",
445 {
446 {5, 25.8947},
447 {10, 24.0721},
448 {15, 22.9698},
449 {20, 22.1738},
450 {25, 21.5437},
451 {30, 21.0186},
452 {35, 20.5650},
453 {40, 20.1654},
454 {45, 19.8059},
455 {50, 19.4784},
456 }},
457 {"HeMcs5_20MHz",
458 {
459 {5, 30.0542},
460 {10, 28.0155},
461 {15, 26.7625},
462 {20, 25.8523},
463 {25, 25.1295},
464 {30, 24.5258},
465 {35, 24.0034},
466 {40, 23.5426},
467 {45, 23.1277},
468 {50, 22.7492},
469 }},
470 {"HeMcs6_20MHz",
471 {
472 {5, 32.6789},
473 {10, 30.5150},
474 {15, 29.1708},
475 {20, 28.1907},
476 {25, 27.4107},
477 {30, 26.7583},
478 {35, 26.1931},
479 {40, 25.6941},
480 {45, 25.2446},
481 {50, 24.8343},
482 }},
483 {"HeMcs7_20MHz",
484 {
485 {5, 34.1710},
486 {10, 31.9398},
487 {15, 30.5451},
488 {20, 29.5261},
489 {25, 28.7140},
490 {30, 28.0342},
491 {35, 27.4449},
492 {40, 26.9245},
493 {45, 26.4554},
494 {50, 26.0271},
495 }},
496 {"HeMcs8_20MHz",
497 {
498 {5, 37.6051},
499 {10, 35.2296},
500 {15, 33.7228},
501 {20, 32.6160},
502 {25, 31.7314},
503 {30, 30.9895},
504 {35, 30.3455},
505 {40, 29.7760},
506 {45, 29.2623},
507 {50, 28.7929},
508 }},
509 {"HeMcs9_20MHz",
510 {
511 {5, 39.5947},
512 {10, 37.1424},
513 {15, 35.5731},
514 {20, 34.4169},
515 {25, 33.4911},
516 {30, 32.7138},
517 {35, 32.0385},
518 {40, 31.4410},
519 {45, 30.9016},
520 {50, 30.4086},
521 }},
522 {"HeMcs10_20MHz",
523 {
524 {5, 39.5947},
525 {10, 37.1424},
526 {15, 35.5731},
527 {20, 34.4169},
528 {25, 33.4911},
529 {30, 32.7138},
530 {35, 32.0385},
531 {40, 31.4410},
532 {45, 30.9016},
533 {50, 30.4086},
534 }},
535 {"HeMcs11_20MHz",
536 {
537 {5, 41.8065},
538 {10, 39.2749},
539 {15, 37.6383},
540 {20, 36.4282},
541 {25, 35.4575},
542 {30, 34.6414},
543 {35, 33.9316},
544 {40, 33.3031},
545 {45, 32.7355},
546 {50, 32.2164},
547 }},
548 {"HeMcs0_40MHz",
549 {
550 {5, 11.4999},
551 {10, 10.5902},
552 {15, 10.0669},
553 {20, 9.6960},
554 {25, 9.4055},
555 {30, 9.1652},
556 {35, 8.9587},
557 {40, 8.7775},
558 {45, 8.6151},
559 {50, 8.4676},
560 }},
561 {"HeMcs1_40MHz",
562 {
563 {5, 19.5937},
564 {10, 18.1394},
565 {15, 17.2798},
566 {20, 16.6642},
567 {25, 16.1793},
568 {30, 15.7766},
569 {35, 15.4295},
570 {40, 15.1242},
571 {45, 14.8502},
572 {50, 14.6007},
573 }},
574 {"HeMcs2_40MHz",
575 {
576 {5, 25.6338},
577 {10, 23.8255},
578 {15, 22.7329},
579 {20, 21.9442},
580 {25, 21.3200},
581 {30, 20.7999},
582 {35, 20.3506},
583 {40, 19.9549},
584 {45, 19.5990},
585 {50, 19.2746},
586 }},
587 {"HeMcs3_40MHz",
588 {
589 {5, 30.0542},
590 {10, 28.0155},
591 {15, 26.7625},
592 {20, 25.8523},
593 {25, 25.1295},
594 {30, 24.5258},
595 {35, 24.0034},
596 {40, 23.5426},
597 {45, 23.1277},
598 {50, 22.7492},
599 }},
600 {"HeMcs4_40MHz",
601 {
602 {5, 37.6051},
603 {10, 35.2296},
604 {15, 33.7228},
605 {20, 32.6160},
606 {25, 31.7314},
607 {30, 30.9895},
608 {35, 30.3455},
609 {40, 29.7760},
610 {45, 29.2623},
611 {50, 28.7929},
612 }},
613 {"HeMcs5_40MHz",
614 {
615 {5, 41.8065},
616 {10, 39.2749},
617 {15, 37.6383},
618 {20, 36.4282},
619 {25, 35.4575},
620 {30, 34.6414},
621 {35, 33.9316},
622 {40, 33.3031},
623 {45, 32.7355},
624 {50, 32.2164},
625 }},
626 {"HeMcs6_40MHz",
627 {
628 {5, 44.2801},
629 {10, 41.6672},
630 {15, 39.9580},
631 {20, 38.6892},
632 {25, 37.6692},
633 {30, 36.8103},
634 {35, 36.0625},
635 {40, 35.3998},
636 {45, 34.8008},
637 {50, 34.2528},
638 }},
639 {"HeMcs7_40MHz",
640 {
641 {5, 44.2801},
642 {10, 41.6672},
643 {15, 39.9580},
644 {20, 38.6892},
645 {25, 37.6692},
646 {30, 36.8103},
647 {35, 36.0625},
648 {40, 35.3998},
649 {45, 34.8008},
650 {50, 34.2528},
651 }},
652 {"HeMcs8_40MHz",
653 {
654 {5, 47.0648},
655 {10, 44.3699},
656 {15, 42.5825},
657 {20, 41.2495},
658 {25, 40.1751},
659 {30, 39.2689},
660 {35, 38.4790},
661 {40, 37.7781},
662 {45, 37.1443},
663 {50, 36.5639},
664 }},
665 {"HeMcs9_40MHz",
666 {
667 {5, 50.2233},
668 {10, 47.4474},
669 {15, 45.5760},
670 {20, 44.1727},
671 {25, 43.0382},
672 {30, 42.0794},
673 {35, 41.2425},
674 {40, 40.4991},
675 {45, 39.8262},
676 {50, 39.2095},
677 }},
678 {"HeMcs10_40MHz",
679 {
680 {5, 50.2233},
681 {10, 47.4474},
682 {15, 45.5760},
683 {20, 44.1727},
684 {25, 43.0382},
685 {30, 42.0794},
686 {35, 41.2425},
687 {40, 40.4991},
688 {45, 39.8262},
689 {50, 39.2095},
690 }},
691 {"HeMcs11_40MHz",
692 {
693 {5, 50.2233},
694 {10, 47.4474},
695 {15, 45.5760},
696 {20, 44.1727},
697 {25, 43.0382},
698 {30, 42.0794},
699 {35, 41.2425},
700 {40, 40.4991},
701 {45, 39.8262},
702 {50, 39.2095},
703 }},
704 {"HeMcs0_80MHz",
705 {
706 {5, 19.6542},
707 {10, 18.1962},
708 {15, 17.3342},
709 {20, 16.7168},
710 {25, 16.2305},
711 {30, 15.8265},
712 {35, 15.4784},
713 {40, 15.1723},
714 {45, 14.8973},
715 {50, 14.6471},
716 }},
717 {"HeMcs1_80MHz",
718 {
719 {5, 30.9311},
720 {10, 28.8495},
721 {15, 27.5657},
722 {20, 26.6320},
723 {25, 25.8899},
724 {30, 25.2699},
725 {35, 24.7332},
726 {40, 24.2595},
727 {45, 23.8330},
728 {50, 23.4439},
729 }},
730 {"HeMcs2_80MHz",
731 {
732 {5, 37.0575},
733 {10, 34.7039},
734 {15, 33.2146},
735 {20, 32.1216},
736 {25, 31.2485},
737 {30, 30.5164},
738 {35, 29.8811},
739 {40, 29.3194},
740 {45, 28.8127},
741 {50, 28.3499},
742 }},
743 {"HeMcs3_80MHz",
744 {
745 {5, 41.8065},
746 {10, 39.2749},
747 {15, 37.6383},
748 {20, 36.4282},
749 {25, 35.4575},
750 {30, 34.6414},
751 {35, 33.9316},
752 {40, 33.3031},
753 {45, 32.7355},
754 {50, 32.2164},
755 }},
756 {"HeMcs4_80MHz",
757 {
758 {5, 47.0648},
759 {10, 44.3699},
760 {15, 42.5825},
761 {20, 41.2495},
762 {25, 40.1751},
763 {30, 39.2689},
764 {35, 38.4790},
765 {40, 37.7781},
766 {45, 37.1443},
767 {50, 36.5639},
768 }},
769 {"HeMcs5_80MHz",
770 {
771 {5, 50.2233},
772 {10, 47.4474},
773 {15, 45.5760},
774 {20, 44.1727},
775 {25, 43.0382},
776 {30, 42.0794},
777 {35, 41.2425},
778 {40, 40.4991},
779 {45, 39.8262},
780 {50, 39.2095},
781 }},
782 {"HeMcs6_80MHz",
783 {
784 {5, 53.8362},
785 {10, 50.9837},
786 {15, 49.0221},
787 {20, 47.5418},
788 {25, 46.3407},
789 {30, 45.3233},
790 {35, 44.4337},
791 {40, 43.6425},
792 {45, 42.9255},
793 {50, 42.2678},
794 }},
795 {"HeMcs7_80MHz",
796 {
797 {5, 53.8362},
798 {10, 50.9837},
799 {15, 49.0221},
800 {20, 47.5418},
801 {25, 46.3407},
802 {30, 45.3233},
803 {35, 44.4337},
804 {40, 43.6425},
805 {45, 42.9255},
806 {50, 42.2678},
807 }},
808 {"HeMcs8_80MHz",
809 {
810 {5, 53.8362},
811 {10, 50.9837},
812 {15, 49.0221},
813 {20, 47.5418},
814 {25, 46.3407},
815 {30, 45.3233},
816 {35, 44.4337},
817 {40, 43.6425},
818 {45, 42.9255},
819 {50, 42.2678},
820 }},
821 {"HeMcs9_80MHz",
822 {
823 {5, 58.0092},
824 {10, 55.0896},
825 {15, 53.0321},
826 {20, 51.4672},
827 {25, 50.1922},
828 {30, 49.1091},
829 {35, 48.1601},
830 {40, 47.3148},
831 {45, 46.5478},
832 {50, 45.8436},
833 }},
834 {"HeMcs10_80MHz",
835 {
836 {5, 58.0092},
837 {10, 55.0896},
838 {15, 53.0321},
839 {20, 51.4672},
840 {25, 50.1922},
841 {30, 49.1091},
842 {35, 48.1601},
843 {40, 47.3148},
844 {45, 46.5478},
845 {50, 45.8436},
846 }},
847 {"HeMcs11_80MHz",
848 {
849 {5, 58.0092},
850 {10, 55.0896},
851 {15, 53.0321},
852 {20, 51.4672},
853 {25, 50.1922},
854 {30, 49.1091},
855 {35, 48.1601},
856 {40, 47.3148},
857 {45, 46.5478},
858 {50, 45.8436},
859 }},
860 {"HeMcs0_160MHz",
861 {
862 {5, 29.8428},
863 {10, 27.8145},
864 {15, 26.5689},
865 {20, 25.6645},
866 {25, 24.9463},
867 {30, 24.3466},
868 {35, 23.8276},
869 {40, 23.3699},
870 {45, 22.9578},
871 {50, 22.5819},
872 }},
873 {"HeMcs1_160MHz",
874 {
875 {5, 41.1308},
876 {10, 38.6227},
877 {15, 37.0064},
878 {20, 35.8126},
879 {25, 34.8556},
880 {30, 34.0513},
881 {35, 33.3520},
882 {40, 32.7329},
883 {45, 32.1739},
884 {50, 31.6628},
885 }},
886 {"HeMcs2_160MHz",
887 {
888 {5, 46.2101},
889 {10, 43.5393},
890 {15, 41.7755},
891 {20, 40.4620},
892 {25, 39.4041},
893 {30, 38.5123},
894 {35, 37.7353},
895 {40, 37.0461},
896 {45, 36.4229},
897 {50, 35.8524},
898 }},
899 {"HeMcs3_160MHz",
900 {
901 {5, 50.2233},
902 {10, 47.4474},
903 {15, 45.5760},
904 {20, 44.1727},
905 {25, 43.0382},
906 {30, 42.0794},
907 {35, 41.2425},
908 {40, 40.4991},
909 {45, 39.8262},
910 {50, 39.2095},
911 }},
912 {"HeMcs4_160MHz",
913 {
914 {5, 53.8362},
915 {10, 50.9837},
916 {15, 49.0221},
917 {20, 47.5418},
918 {25, 46.3407},
919 {30, 45.3233},
920 {35, 44.4337},
921 {40, 43.6425},
922 {45, 42.9255},
923 {50, 42.2678},
924 }},
925 {"HeMcs5_160MHz",
926 {
927 {5, 58.0092},
928 {10, 55.0896},
929 {15, 53.0321},
930 {20, 51.4672},
931 {25, 50.1922},
932 {30, 49.1091},
933 {35, 48.1601},
934 {40, 47.3148},
935 {45, 46.5478},
936 {50, 45.8436},
937 }},
938 {"HeMcs6_160MHz",
939 {
940 {5, 58.0092},
941 {10, 55.0896},
942 {15, 53.0321},
943 {20, 51.4672},
944 {25, 50.1922},
945 {30, 49.1091},
946 {35, 48.1601},
947 {40, 47.3148},
948 {45, 46.5478},
949 {50, 45.8436},
950 }},
951 {"HeMcs7_160MHz",
952 {
953 {5, 58.0092},
954 {10, 55.0896},
955 {15, 53.0321},
956 {20, 51.4672},
957 {25, 50.1922},
958 {30, 49.1091},
959 {35, 48.1601},
960 {40, 47.3148},
961 {45, 46.5478},
962 {50, 45.8436},
963 }},
964 {"HeMcs8_160MHz",
965 {
966 {5, 58.0092},
967 {10, 55.0896},
968 {15, 53.0321},
969 {20, 51.4672},
970 {25, 50.1922},
971 {30, 49.1091},
972 {35, 48.1601},
973 {40, 47.3148},
974 {45, 46.5478},
975 {50, 45.8436},
976 }},
977 {"HeMcs9_160MHz",
978 {
979 {5, 62.8834},
980 {10, 59.9147},
981 {15, 57.7564},
982 {20, 56.0992},
983 {25, 54.7419},
984 {30, 53.5850},
985 {35, 52.5689},
986 {40, 51.6620},
987 {45, 50.8379},
988 {50, 50.0803},
989 }},
990 {"HeMcs10_160MHz",
991 {
992 {5, 62.8834},
993 {10, 59.9147},
994 {15, 57.7564},
995 {20, 56.0992},
996 {25, 54.7419},
997 {30, 53.5850},
998 {35, 52.5689},
999 {40, 51.6620},
1000 {45, 50.8379},
1001 {50, 50.0803},
1002 }},
1003 {"HeMcs11_160MHz",
1004 {
1005 {5, 62.8834},
1006 {10, 59.9147},
1007 {15, 57.7564},
1008 {20, 56.0992},
1009 {25, 54.7419},
1010 {30, 53.5850},
1011 {35, 52.5689},
1012 {40, 51.6620},
1013 {45, 50.8379},
1014 {50, 50.0803},
1015 }},
1016};
1017
1018/// Table of the expected values for DIFS
1019std::map<std::string /* mode */,
1020 std::map<unsigned int /* number of nodes */, double /* calculated throughput */>>
1022 /* 11b */
1023 {"DsssRate1Mbps",
1024 {
1025 {5, 0.8437},
1026 {10, 0.7861},
1027 {15, 0.7496},
1028 {20, 0.7226},
1029 {25, 0.7016},
1030 {30, 0.6847},
1031 {35, 0.6686},
1032 {40, 0.6549},
1033 {45, 0.6435},
1034 {50, 0.6336},
1035 }},
1036 {"DsssRate2Mbps",
1037 {
1038 {5, 1.6228},
1039 {10, 1.5168},
1040 {15, 1.4482},
1041 {20, 1.3972},
1042 {25, 1.3574},
1043 {30, 1.3253},
1044 {35, 1.2947},
1045 {40, 1.2687},
1046 {45, 1.2469},
1047 {50, 1.2279},
1048 }},
1049 {"DsssRate5_5Mbps",
1050 {
1051 {5, 3.8896},
1052 {10, 3.6707},
1053 {15, 3.5203},
1054 {20, 3.4063},
1055 {25, 3.3161},
1056 {30, 3.2429},
1057 {35, 3.1729},
1058 {40, 3.1128},
1059 {45, 3.0625},
1060 {50, 3.0184},
1061 }},
1062 {"DsssRate11Mbps",
1063 {
1064 {5, 6.4734},
1065 {10, 6.1774},
1066 {15, 5.9553},
1067 {20, 5.7819},
1068 {25, 5.6429},
1069 {30, 5.5289},
1070 {35, 5.4191},
1071 {40, 5.3243},
1072 {45, 5.2446},
1073 {50, 5.1745},
1074 }},
1075 /* 11a */
1076 {"OfdmRate6Mbps",
1077 {
1078 {5, 4.7087},
1079 {10, 4.3453},
1080 {15, 4.1397},
1081 {20, 3.9899},
1082 {25, 3.8802},
1083 {30, 3.7824},
1084 {35, 3.6961},
1085 {40, 3.6276},
1086 {45, 3.5712},
1087 {50, 3.5071},
1088 }},
1089 {"OfdmRate9Mbps",
1090 {
1091 {5, 6.8586},
1092 {10, 6.3431},
1093 {15, 6.0489},
1094 {20, 5.8340},
1095 {25, 5.6762},
1096 {30, 5.5355},
1097 {35, 5.4110},
1098 {40, 5.3122},
1099 {45, 5.2307},
1100 {50, 5.1380},
1101 }},
1102 {"OfdmRate12Mbps",
1103 {
1104 {5, 8.9515},
1105 {10, 8.2901},
1106 {15, 7.9102},
1107 {20, 7.6319},
1108 {25, 7.4274},
1109 {30, 7.2447},
1110 {35, 7.0829},
1111 {40, 6.9544},
1112 {45, 6.8485},
1113 {50, 6.7278},
1114 }},
1115 {"OfdmRate18Mbps",
1116 {
1117 {5, 12.7822},
1118 {10, 11.8801},
1119 {15, 11.3543},
1120 {20, 10.9668},
1121 {25, 10.6809},
1122 {30, 10.4249},
1123 {35, 10.1978},
1124 {40, 10.0171},
1125 {45, 9.8679},
1126 {50, 9.6978},
1127 }},
1128 {"OfdmRate24Mbps",
1129 {
1130 {5, 16.2470},
1131 {10, 15.1426},
1132 {15, 14.4904},
1133 {20, 14.0072},
1134 {25, 13.6496},
1135 {30, 13.3288},
1136 {35, 13.0436},
1137 {40, 12.8164},
1138 {45, 12.6286},
1139 {50, 12.4144},
1140 }},
1141 {"OfdmRate36Mbps",
1142 {
1143 {5, 22.3164},
1144 {10, 20.9147},
1145 {15, 20.0649},
1146 {20, 19.4289},
1147 {25, 18.9552},
1148 {30, 18.5284},
1149 {35, 18.1476},
1150 {40, 17.8434},
1151 {45, 17.5915},
1152 {50, 17.3036},
1153 }},
1154 {"OfdmRate48Mbps",
1155 {
1156 {5, 27.2963},
1157 {10, 25.6987},
1158 {15, 24.7069},
1159 {20, 23.9578},
1160 {25, 23.3965},
1161 {30, 22.8891},
1162 {35, 22.4350},
1163 {40, 22.0713},
1164 {45, 21.7696},
1165 {50, 21.4243},
1166 }},
1167 {"OfdmRate54Mbps",
1168 {
1169 {5, 29.8324},
1170 {10, 28.1519},
1171 {15, 27.0948},
1172 {20, 26.2925},
1173 {25, 25.6896},
1174 {30, 25.1434},
1175 {35, 24.6539},
1176 {40, 24.2613},
1177 {45, 23.9353},
1178 {50, 23.5618},
1179 }},
1180 /* 11g */
1181 {"ErpOfdmRate6Mbps",
1182 {
1183 {5, 4.7087},
1184 {10, 4.3453},
1185 {15, 4.1397},
1186 {20, 3.9899},
1187 {25, 3.8802},
1188 {30, 3.7824},
1189 {35, 3.6961},
1190 {40, 3.6276},
1191 {45, 3.5712},
1192 {50, 3.5071},
1193 }},
1194 {"ErpOfdmRate9Mbps",
1195 {
1196 {5, 6.8586},
1197 {10, 6.3431},
1198 {15, 6.0489},
1199 {20, 5.8340},
1200 {25, 5.6762},
1201 {30, 5.5355},
1202 {35, 5.4110},
1203 {40, 5.3122},
1204 {45, 5.2307},
1205 {50, 5.1380},
1206 }},
1207 {"ErpOfdmRate12Mbps",
1208 {
1209 {5, 8.9515},
1210 {10, 8.2901},
1211 {15, 7.9102},
1212 {20, 7.6319},
1213 {25, 7.4274},
1214 {30, 7.2447},
1215 {35, 7.0829},
1216 {40, 6.9544},
1217 {45, 6.8485},
1218 {50, 6.7278},
1219 }},
1220 {"ErpOfdmRate18Mbps",
1221 {
1222 {5, 12.7822},
1223 {10, 11.8801},
1224 {15, 11.3543},
1225 {20, 10.9668},
1226 {25, 10.6809},
1227 {30, 10.4249},
1228 {35, 10.1978},
1229 {40, 10.0171},
1230 {45, 9.8679},
1231 {50, 9.6978},
1232 }},
1233 {"ErpOfdmRate24Mbps",
1234 {
1235 {5, 16.2470},
1236 {10, 15.1426},
1237 {15, 14.4904},
1238 {20, 14.0072},
1239 {25, 13.6496},
1240 {30, 13.3288},
1241 {35, 13.0436},
1242 {40, 12.8164},
1243 {45, 12.6286},
1244 {50, 12.4144},
1245 }},
1246 {"ErpOfdmRate36Mbps",
1247 {
1248 {5, 22.3164},
1249 {10, 20.9147},
1250 {15, 20.0649},
1251 {20, 19.4289},
1252 {25, 18.9552},
1253 {30, 18.5284},
1254 {35, 18.1476},
1255 {40, 17.8434},
1256 {45, 17.5915},
1257 {50, 17.3036},
1258 }},
1259 {"ErpOfdmRate48Mbps",
1260 {
1261 {5, 27.2963},
1262 {10, 25.6987},
1263 {15, 24.7069},
1264 {20, 23.9578},
1265 {25, 23.3965},
1266 {30, 22.8891},
1267 {35, 22.4350},
1268 {40, 22.0713},
1269 {45, 21.7696},
1270 {50, 21.4243},
1271 }},
1272 {"ErpOfdmRate54Mbps",
1273 {
1274 {5, 29.8324},
1275 {10, 28.1519},
1276 {15, 27.0948},
1277 {20, 26.2925},
1278 {25, 25.6896},
1279 {30, 25.1434},
1280 {35, 24.6539},
1281 {40, 24.2613},
1282 {45, 23.9353},
1283 {50, 23.5618},
1284 }},
1285 /* 11ax, no frame aggregation */
1286 {"HeMcs0_20MHz",
1287 {
1288 {5, 6.3746},
1289 {10, 5.8670},
1290 {15, 5.5782},
1291 {20, 5.3742},
1292 {25, 5.2147},
1293 {30, 5.0829},
1294 {35, 4.9696},
1295 {40, 4.8703},
1296 {45, 4.7813},
1297 {50, 4.7004},
1298 }},
1299 {"HeMcs1_20MHz",
1300 {
1301 {5, 11.7574},
1302 {10, 10.8735},
1303 {15, 10.3606},
1304 {20, 9.9954},
1305 {25, 9.7084},
1306 {30, 9.4704},
1307 {35, 9.2654},
1308 {40, 9.0853},
1309 {45, 8.9235},
1310 {50, 8.7763},
1311 }},
1312 {"HeMcs2_20MHz",
1313 {
1314 {5, 16.0419},
1315 {10, 14.8998},
1316 {15, 14.2252},
1317 {20, 13.7413},
1318 {25, 13.3594},
1319 {30, 13.0417},
1320 {35, 12.7674},
1321 {40, 12.5258},
1322 {45, 12.3086},
1323 {50, 12.1107},
1324 }},
1325 {"HeMcs3_20MHz",
1326 {
1327 {5, 20.0089},
1328 {10, 18.6480},
1329 {15, 17.8309},
1330 {20, 17.2410},
1331 {25, 16.7736},
1332 {30, 16.3837},
1333 {35, 16.0465},
1334 {40, 15.7491},
1335 {45, 15.4813},
1336 {50, 15.2369},
1337 }},
1338 {"HeMcs4_20MHz",
1339 {
1340 {5, 26.3492},
1341 {10, 24.7107},
1342 {15, 23.6964},
1343 {20, 22.9553},
1344 {25, 22.3640},
1345 {30, 21.8683},
1346 {35, 21.4379},
1347 {40, 21.0571},
1348 {45, 20.7134},
1349 {50, 20.3991},
1350 }},
1351 {"HeMcs5_20MHz",
1352 {
1353 {5, 30.6683},
1354 {10, 28.8843},
1355 {15, 27.7540},
1356 {20, 26.9210},
1357 {25, 26.2528},
1358 {30, 25.6906},
1359 {35, 25.2012},
1360 {40, 24.7671},
1361 {45, 24.3746},
1362 {50, 24.0151},
1363 }},
1364 {"HeMcs6_20MHz",
1365 {
1366 {5, 33.4062},
1367 {10, 31.5485},
1368 {15, 30.3527},
1369 {20, 29.4662},
1370 {25, 28.7527},
1371 {30, 28.1508},
1372 {35, 27.6259},
1373 {40, 27.1597},
1374 {45, 26.7376},
1375 {50, 26.3507},
1376 }},
1377 {"HeMcs7_20MHz",
1378 {
1379 {5, 34.9671},
1380 {10, 33.0739},
1381 {15, 31.8436},
1382 {20, 30.9282},
1383 {25, 30.1900},
1384 {30, 29.5665},
1385 {35, 29.0221},
1386 {40, 28.5382},
1387 {45, 28.0997},
1388 {50, 27.6975},
1389 }},
1390 {"HeMcs8_20MHz",
1391 {
1392 {5, 38.5714},
1393 {10, 36.6144},
1394 {15, 35.3124},
1395 {20, 34.3355},
1396 {25, 33.5438},
1397 {30, 32.8728},
1398 {35, 32.2854},
1399 {40, 31.7623},
1400 {45, 31.2874},
1401 {50, 30.8512},
1402 }},
1403 {"HeMcs9_20MHz",
1404 {
1405 {5, 40.6674},
1406 {10, 38.6851},
1407 {15, 37.3466},
1408 {20, 36.3371},
1409 {25, 35.5165},
1410 {30, 34.8197},
1411 {35, 34.2087},
1412 {40, 33.6638},
1413 {45, 33.1688},
1414 {50, 32.7137},
1415 }},
1416 {"HeMcs10_20MHz",
1417 {
1418 {5, 40.6674},
1419 {10, 38.6851},
1420 {15, 37.3466},
1421 {20, 36.3371},
1422 {25, 35.5165},
1423 {30, 34.8197},
1424 {35, 34.2087},
1425 {40, 33.6638},
1426 {45, 33.1688},
1427 {50, 32.7137},
1428 }},
1429 {"HeMcs11_20MHz",
1430 {
1431 {5, 43.0043},
1432 {10, 41.0039},
1433 {15, 39.6294},
1434 {20, 38.5865},
1435 {25, 37.7358},
1436 {30, 37.0116},
1437 {35, 36.3756},
1438 {40, 35.8076},
1439 {45, 35.2909},
1440 {50, 34.8154},
1441 }},
1442 {"HeMcs0_40MHz",
1443 {
1444 {5, 11.6208},
1445 {10, 10.7566},
1446 {15, 10.2544},
1447 {20, 9.8965},
1448 {25, 9.6151},
1449 {30, 9.3815},
1450 {35, 9.1804},
1451 {40, 9.0035},
1452 {45, 8.8446},
1453 {50, 8.7000},
1454 }},
1455 {"HeMcs1_40MHz",
1456 {
1457 {5, 19.8764},
1458 {10, 18.5328},
1459 {15, 17.7255},
1460 {20, 17.1424},
1461 {25, 16.6803},
1462 {30, 16.2947},
1463 {35, 15.9612},
1464 {40, 15.6668},
1465 {45, 15.4018},
1466 {50, 15.1599},
1467 }},
1468 {"HeMcs2_40MHz",
1469 {
1470 {5, 26.1198},
1471 {10, 24.5088},
1472 {15, 23.5107},
1473 {20, 22.7810},
1474 {25, 22.1986},
1475 {30, 21.7101},
1476 {35, 21.2858},
1477 {40, 20.9104},
1478 {45, 20.5714},
1479 {50, 20.2613},
1480 }},
1481 {"HeMcs3_40MHz",
1482 {
1483 {5, 30.6683},
1484 {10, 28.8843},
1485 {15, 27.7540},
1486 {20, 26.9210},
1487 {25, 26.2528},
1488 {30, 25.6906},
1489 {35, 25.2012},
1490 {40, 24.7671},
1491 {45, 24.3746},
1492 {50, 24.0151},
1493 }},
1494 {"HeMcs4_40MHz",
1495 {
1496 {5, 38.5714},
1497 {10, 36.6144},
1498 {15, 35.3124},
1499 {20, 34.3355},
1500 {25, 33.5438},
1501 {30, 32.8728},
1502 {35, 32.2854},
1503 {40, 31.7623},
1504 {45, 31.2874},
1505 {50, 30.8512},
1506 }},
1507 {"HeMcs5_40MHz",
1508 {
1509 {5, 43.0043},
1510 {10, 41.0039},
1511 {15, 39.6294},
1512 {20, 38.5865},
1513 {25, 37.7358},
1514 {30, 37.0116},
1515 {35, 36.3756},
1516 {40, 35.8076},
1517 {45, 35.2909},
1518 {50, 34.8154},
1519 }},
1520 {"HeMcs6_40MHz",
1521 {
1522 {5, 45.6261},
1523 {10, 43.6185},
1524 {15, 42.2095},
1525 {20, 41.1328},
1526 {25, 40.2509},
1527 {30, 39.4981},
1528 {35, 38.8356},
1529 {40, 38.2430},
1530 {45, 37.7032},
1531 {50, 37.2058},
1532 }},
1533 {"HeMcs7_40MHz",
1534 {
1535 {5, 45.6261},
1536 {10, 43.6185},
1537 {15, 42.2095},
1538 {20, 41.1328},
1539 {25, 40.2509},
1540 {30, 39.4981},
1541 {35, 38.8356},
1542 {40, 38.2430},
1543 {45, 37.7032},
1544 {50, 37.2058},
1545 }},
1546 {"HeMcs8_40MHz",
1547 {
1548 {5, 48.5883},
1549 {10, 46.5892},
1550 {15, 45.1489},
1551 {20, 44.0388},
1552 {25, 43.1252},
1553 {30, 42.3428},
1554 {35, 41.6525},
1555 {40, 41.0338},
1556 {45, 40.4694},
1557 {50, 39.9486},
1558 }},
1559 {"HeMcs9_40MHz",
1560 {
1561 {5, 51.9619},
1562 {10, 49.9941},
1563 {15, 48.5284},
1564 {20, 47.3867},
1565 {25, 46.4416},
1566 {30, 45.6290},
1567 {35, 44.9099},
1568 {40, 44.2640},
1569 {45, 43.6736},
1570 {50, 43.1279},
1571 }},
1572 {"HeMcs10_40MHz",
1573 {
1574 {5, 51.9619},
1575 {10, 49.9941},
1576 {15, 48.5284},
1577 {20, 47.3867},
1578 {25, 46.4416},
1579 {30, 45.6290},
1580 {35, 44.9099},
1581 {40, 44.2640},
1582 {45, 43.6736},
1583 {50, 43.1279},
1584 }},
1585 {"HeMcs11_40MHz",
1586 {
1587 {5, 51.9619},
1588 {10, 49.9941},
1589 {15, 48.5284},
1590 {20, 47.3867},
1591 {25, 46.4416},
1592 {30, 45.6290},
1593 {35, 44.9099},
1594 {40, 44.2640},
1595 {45, 43.6736},
1596 {50, 43.1279},
1597 }},
1598 {"HeMcs0_80MHz",
1599 {
1600 {5, 20.0101},
1601 {10, 18.6928},
1602 {15, 17.8976},
1603 {20, 17.3219},
1604 {25, 16.8648},
1605 {30, 16.4830},
1606 {35, 16.1523},
1607 {40, 15.8603},
1608 {45, 15.5971},
1609 {50, 15.3567},
1610 }},
1611 {"HeMcs1_80MHz",
1612 {
1613 {5, 31.6415},
1614 {10, 29.8575},
1615 {15, 28.7177},
1616 {20, 27.8747},
1617 {25, 27.1971},
1618 {30, 26.6261},
1619 {35, 26.1283},
1620 {40, 25.6865},
1621 {45, 25.2866},
1622 {50, 24.9200},
1623 }},
1624 {"HeMcs2_80MHz",
1625 {
1626 {5, 38.0818},
1627 {10, 36.1730},
1628 {15, 34.9016},
1629 {20, 33.9470},
1630 {25, 33.1729},
1631 {30, 32.5165},
1632 {35, 31.9417},
1633 {40, 31.4295},
1634 {45, 30.9645},
1635 {50, 30.5372},
1636 }},
1637 {"HeMcs3_80MHz",
1638 {
1639 {5, 43.0043},
1640 {10, 41.0039},
1641 {15, 39.6294},
1642 {20, 38.5865},
1643 {25, 37.7358},
1644 {30, 37.0116},
1645 {35, 36.3756},
1646 {40, 35.8076},
1647 {45, 35.2909},
1648 {50, 34.8154},
1649 }},
1650 {"HeMcs4_80MHz",
1651 {
1652 {5, 48.5883},
1653 {10, 46.5892},
1654 {15, 45.1489},
1655 {20, 44.0388},
1656 {25, 43.1252},
1657 {30, 42.3428},
1658 {35, 41.6525},
1659 {40, 41.0338},
1660 {45, 40.4694},
1661 {50, 39.9486},
1662 }},
1663 {"HeMcs5_80MHz",
1664 {
1665 {5, 51.9619},
1666 {10, 49.9941},
1667 {15, 48.5284},
1668 {20, 47.3867},
1669 {25, 46.4416},
1670 {30, 45.6290},
1671 {35, 44.9099},
1672 {40, 44.2640},
1673 {45, 43.6736},
1674 {50, 43.1279},
1675 }},
1676 {"HeMcs6_80MHz",
1677 {
1678 {5, 55.8389},
1679 {10, 53.9360},
1680 {15, 52.4548},
1681 {20, 51.2855},
1682 {25, 50.3106},
1683 {30, 49.4682},
1684 {35, 48.7201},
1685 {40, 48.0462},
1686 {45, 47.4288},
1687 {50, 46.8571},
1688 }},
1689 {"HeMcs7_80MHz",
1690 {
1691 {5, 55.8389},
1692 {10, 53.9360},
1693 {15, 52.4548},
1694 {20, 51.2855},
1695 {25, 50.3106},
1696 {30, 49.4682},
1697 {35, 48.7201},
1698 {40, 48.0462},
1699 {45, 47.4288},
1700 {50, 46.8571},
1701 }},
1702 {"HeMcs8_80MHz",
1703 {
1704 {5, 55.8389},
1705 {10, 53.9360},
1706 {15, 52.4548},
1707 {20, 51.2855},
1708 {25, 50.3106},
1709 {30, 49.4682},
1710 {35, 48.7201},
1711 {40, 48.0462},
1712 {45, 47.4288},
1713 {50, 46.8571},
1714 }},
1715 {"HeMcs9_80MHz",
1716 {
1717 {5, 60.3411},
1718 {10, 58.5527},
1719 {15, 57.0724},
1720 {20, 55.8834},
1721 {25, 54.8827},
1722 {30, 54.0128},
1723 {35, 53.2368},
1724 {40, 52.5352},
1725 {45, 51.8906},
1726 {50, 51.2922},
1727 }},
1728 {"HeMcs10_80MHz",
1729 {
1730 {5, 60.3411},
1731 {10, 58.5527},
1732 {15, 57.0724},
1733 {20, 55.8834},
1734 {25, 54.8827},
1735 {30, 54.0128},
1736 {35, 53.2368},
1737 {40, 52.5352},
1738 {45, 51.8906},
1739 {50, 51.2922},
1740 }},
1741 {"HeMcs11_80MHz",
1742 {
1743 {5, 60.3411},
1744 {10, 58.5527},
1745 {15, 57.0724},
1746 {20, 55.8834},
1747 {25, 54.8827},
1748 {30, 54.0128},
1749 {35, 53.2368},
1750 {40, 52.5352},
1751 {45, 51.8906},
1752 {50, 51.2922},
1753 }},
1754 {"HeMcs0_160MHz",
1755 {
1756 {5, 30.6710},
1757 {10, 28.9919},
1758 {15, 27.9160},
1759 {20, 27.1188},
1760 {25, 26.4770},
1761 {30, 25.9355},
1762 {35, 25.4630},
1763 {40, 25.0432},
1764 {45, 24.6629},
1765 {50, 24.3141},
1766 }},
1767 {"HeMcs1_160MHz",
1768 {
1769 {5, 42.3965},
1770 {10, 40.4510},
1771 {15, 39.1127},
1772 {20, 38.0965},
1773 {25, 37.2670},
1774 {30, 36.5606},
1775 {35, 35.9398},
1776 {40, 35.3852},
1777 {45, 34.8806},
1778 {50, 34.4160},
1779 }},
1780 {"HeMcs2_160MHz",
1781 {
1782 {5, 47.8139},
1783 {10, 45.8767},
1784 {15, 44.4795},
1785 {20, 43.4017},
1786 {25, 42.5141},
1787 {30, 41.7535},
1788 {35, 41.0821},
1789 {40, 40.4801},
1790 {45, 39.9307},
1791 {50, 39.4236},
1792 }},
1793 {"HeMcs3_160MHz",
1794 {
1795 {5, 51.9619},
1796 {10, 49.9941},
1797 {15, 48.5284},
1798 {20, 47.3867},
1799 {25, 46.4416},
1800 {30, 45.6290},
1801 {35, 44.9099},
1802 {40, 44.2640},
1803 {45, 43.6736},
1804 {50, 43.1279},
1805 }},
1806 {"HeMcs4_160MHz",
1807 {
1808 {5, 55.8389},
1809 {10, 53.9360},
1810 {15, 52.4548},
1811 {20, 51.2855},
1812 {25, 50.3106},
1813 {30, 49.4682},
1814 {35, 48.7201},
1815 {40, 48.0462},
1816 {45, 47.4288},
1817 {50, 46.8571},
1818 }},
1819 {"HeMcs5_160MHz",
1820 {
1821 {5, 60.3411},
1822 {10, 58.5527},
1823 {15, 57.0724},
1824 {20, 55.8834},
1825 {25, 54.8827},
1826 {30, 54.0128},
1827 {35, 53.2368},
1828 {40, 52.5352},
1829 {45, 51.8906},
1830 {50, 51.2922},
1831 }},
1832 {"HeMcs6_160MHz",
1833 {
1834 {5, 60.3411},
1835 {10, 58.5527},
1836 {15, 57.0724},
1837 {20, 55.8834},
1838 {25, 54.8827},
1839 {30, 54.0128},
1840 {35, 53.2368},
1841 {40, 52.5352},
1842 {45, 51.8906},
1843 {50, 51.2922},
1844 }},
1845 {"HeMcs7_160MHz",
1846 {
1847 {5, 60.3411},
1848 {10, 58.5527},
1849 {15, 57.0724},
1850 {20, 55.8834},
1851 {25, 54.8827},
1852 {30, 54.0128},
1853 {35, 53.2368},
1854 {40, 52.5352},
1855 {45, 51.8906},
1856 {50, 51.2922},
1857 }},
1858 {"HeMcs8_160MHz",
1859 {
1860 {5, 60.3411},
1861 {10, 58.5527},
1862 {15, 57.0724},
1863 {20, 55.8834},
1864 {25, 54.8827},
1865 {30, 54.0128},
1866 {35, 53.2368},
1867 {40, 52.5352},
1868 {45, 51.8906},
1869 {50, 51.2922},
1870 }},
1871 {"HeMcs9_160MHz",
1872 {
1873 {5, 65.6329},
1874 {10, 64.0336},
1875 {15, 62.5814},
1876 {20, 61.3869},
1877 {25, 60.3690},
1878 {30, 59.4769},
1879 {35, 58.6764},
1880 {40, 57.9495},
1881 {45, 57.2790},
1882 {50, 56.6548},
1883 }},
1884 {"HeMcs10_160MHz",
1885 {
1886 {5, 65.6329},
1887 {10, 64.0336},
1888 {15, 62.5814},
1889 {20, 61.3869},
1890 {25, 60.3690},
1891 {30, 59.4769},
1892 {35, 58.6764},
1893 {40, 57.9495},
1894 {45, 57.2790},
1895 {50, 56.6548},
1896 }},
1897 {"HeMcs11_160MHz",
1898 {
1899 {5, 65.6329},
1900 {10, 64.0336},
1901 {15, 62.5814},
1902 {20, 61.3869},
1903 {25, 60.3690},
1904 {30, 59.4769},
1905 {35, 58.6764},
1906 {40, 57.9495},
1907 {45, 57.2790},
1908 {50, 56.6548},
1909 }},
1910};
1911
1912/**
1913 * Parse context strings of the form "/NodeList/x/DeviceList/x/..." to extract the NodeId integer
1914 *
1915 * @param context The context to parse.
1916 * @return the NodeId
1917 */
1919ContextToNodeId(std::string context)
1920{
1921 std::string sub = context.substr(10);
1922 uint32_t pos = sub.find("/Device");
1923 return std::stoi(sub.substr(0, pos));
1924}
1925
1926/**
1927 * Parse context strings of the form "/NodeList/x/DeviceList/x/..." and fetch the Mac address
1928 *
1929 * @param context The context to parse.
1930 * @return the device MAC address
1931 */
1933ContextToMac(std::string context)
1934{
1935 std::string sub = context.substr(10);
1936 uint32_t pos = sub.find("/Device");
1937 uint32_t nodeId = std::stoi(sub.substr(0, pos));
1938 Ptr<Node> n = NodeList::GetNode(nodeId);
1940 for (uint32_t i = 0; i < n->GetNDevices(); i++)
1941 {
1942 d = n->GetDevice(i)->GetObject<WifiNetDevice>();
1943 if (d)
1944 {
1945 break;
1946 }
1947 }
1948 return Mac48Address::ConvertFrom(d->GetAddress());
1949}
1950
1951// Functions for tracing.
1952
1953/**
1954 * Increment the counter for a given address.
1955 *
1956 * @param [out] counter The counter to increment.
1957 * @param addr The address to increment the counter for.
1958 * @param increment The increment (1 if omitted).
1959 */
1960void
1961IncrementCounter(std::map<Mac48Address, uint64_t>& counter,
1962 Mac48Address addr,
1963 uint64_t increment = 1)
1964{
1965 auto it = counter.find(addr);
1966 if (it != counter.end())
1967 {
1968 it->second += increment;
1969 }
1970 else
1971 {
1972 counter.insert(std::make_pair(addr, increment));
1973 }
1974}
1975
1976/**
1977 * Trace a packet reception.
1978 *
1979 * @param context The context.
1980 * @param p The packet.
1981 * @param channelFreqMhz The channel frequqncy.
1982 * @param txVector The TX vector.
1983 * @param aMpdu The AMPDU.
1984 * @param signalNoise The signal and noise dBm.
1985 * @param staId The STA ID.
1986 */
1987void
1988TracePacketReception(std::string context,
1990 uint16_t channelFreqMhz,
1991 WifiTxVector txVector,
1992 MpduInfo aMpdu,
1993 SignalNoiseDbm signalNoise,
1994 uint16_t staId)
1995{
1996 Ptr<Packet> packet = p->Copy();
1997 if (txVector.IsAggregation())
1998 {
1999 AmpduSubframeHeader subHdr;
2000 uint32_t extractedLength;
2001 packet->RemoveHeader(subHdr);
2002 extractedLength = subHdr.GetLength();
2003 packet = packet->CreateFragment(0, static_cast<uint32_t>(extractedLength));
2004 }
2005 WifiMacHeader hdr;
2006 packet->PeekHeader(hdr);
2007 // hdr.GetAddr1() is the receiving MAC address
2008 if (hdr.GetAddr1() != ContextToMac(context))
2009 {
2010 return;
2011 }
2012 // hdr.GetAddr2() is the sending MAC address
2013 if (packet->GetSize() >= pktSize) // ignore non-data frames
2014 {
2017 auto itTimeFirstReceived = timeFirstReceived.find(hdr.GetAddr2());
2018 if (itTimeFirstReceived == timeFirstReceived.end())
2019 {
2020 timeFirstReceived.insert(std::make_pair(hdr.GetAddr2(), Simulator::Now()));
2021 }
2022 auto itTimeLastReceived = timeLastReceived.find(hdr.GetAddr2());
2023 if (itTimeLastReceived != timeLastReceived.end())
2024 {
2025 itTimeLastReceived->second = Simulator::Now();
2026 }
2027 else
2028 {
2029 timeLastReceived.insert(std::make_pair(hdr.GetAddr2(), Simulator::Now()));
2030 }
2031 }
2032}
2033
2034/**
2035 * Contention window trace.
2036 *
2037 * @param context The context.
2038 * @param cw The contention window.
2039 */
2040void
2041CwTrace(std::string context, uint32_t cw, uint8_t /* linkId */)
2042{
2043 NS_LOG_INFO("CW time=" << Simulator::Now() << " node=" << ContextToNodeId(context)
2044 << " val=" << cw);
2045 if (tracing)
2046 {
2047 cwTraceFile << Simulator::Now().GetSeconds() << " " << ContextToNodeId(context) << " " << cw
2048 << std::endl;
2049 }
2050}
2051
2052/**
2053 * Backoff trace.
2054 *
2055 * @param context The context.
2056 * @param newVal The backoff value.
2057 */
2058void
2059BackoffTrace(std::string context, uint32_t newVal, uint8_t /* linkId */)
2060{
2061 NS_LOG_INFO("Backoff time=" << Simulator::Now() << " node=" << ContextToNodeId(context)
2062 << " val=" << newVal);
2063 if (tracing)
2064 {
2065 backoffTraceFile << Simulator::Now().GetSeconds() << " " << ContextToNodeId(context) << " "
2066 << newVal << std::endl;
2067 }
2068}
2069
2070/**
2071 * PHY Rx trace.
2072 *
2073 * @param context The context.
2074 * @param p The packet.
2075 * @param power The Rx power.
2076 */
2077void
2079{
2080 NS_LOG_INFO("PHY-RX-START time=" << Simulator::Now() << " node=" << ContextToNodeId(context)
2081 << " size=" << p->GetSize());
2082}
2083
2084/**
2085 * PHY Rx trace.
2086 *
2087 * @param context The context.
2088 * @param txVector The TX vector.
2089 * @param psduDuration The PDSU diration.
2090 */
2091void
2092PhyRxPayloadTrace(std::string context, WifiTxVector txVector, Time psduDuration)
2093{
2094 NS_LOG_INFO("PHY-RX-PAYLOAD-START time=" << Simulator::Now()
2095 << " node=" << ContextToNodeId(context)
2096 << " psduDuration=" << psduDuration);
2097}
2098
2099/**
2100 * PHY Drop trace.
2101 *
2102 * @param context The context.
2103 * @param p The packet.
2104 * @param reason The drop reason.
2105 */
2106void
2108{
2109 NS_LOG_INFO("PHY-RX-DROP time=" << Simulator::Now() << " node=" << ContextToNodeId(context)
2110 << " size=" << p->GetSize() << " reason=" << reason);
2111 Mac48Address addr = ContextToMac(context);
2112 switch (reason)
2113 {
2115 NS_FATAL_ERROR("RX packet with unsupported settings!");
2116 break;
2117 case CHANNEL_SWITCHING:
2118 NS_FATAL_ERROR("Channel is switching!");
2119 break;
2121 if (p->GetSize() >= pktSize) // ignore non-data frames
2122 {
2124 }
2125 break;
2126 }
2127 case RXING: {
2128 if (p->GetSize() >= pktSize) // ignore non-data frames
2129 {
2131 }
2132 break;
2133 }
2134 case TXING: {
2135 if (p->GetSize() >= pktSize) // ignore non-data frames
2136 {
2138 }
2139 break;
2140 }
2141 case SLEEPING:
2142 NS_FATAL_ERROR("Device is sleeping!");
2143 break;
2145 NS_FATAL_ERROR("Preamble should always be detected!");
2146 break;
2148 if (p->GetSize() >= pktSize) // ignore non-data frames
2149 {
2151 }
2152 break;
2153 }
2154 case L_SIG_FAILURE: {
2155 if (p->GetSize() >= pktSize) // ignore non-data frames
2156 {
2158 }
2159 break;
2160 }
2161 case HT_SIG_FAILURE:
2162 case SIG_A_FAILURE:
2163 case SIG_B_FAILURE:
2164 NS_FATAL_ERROR("Unexpected PHY header failure!");
2166 NS_FATAL_ERROR("All devices should send with same power, so no packet switch during "
2167 "preamble detection should occur!");
2168 break;
2170 NS_FATAL_ERROR("Frame capture should be disabled!");
2171 break;
2172 case OBSS_PD_CCA_RESET:
2173 NS_FATAL_ERROR("Unexpected CCA reset!");
2174 break;
2176 break;
2177 case UNKNOWN:
2178 default:
2179 NS_FATAL_ERROR("Unknown drop reason!");
2180 break;
2181 }
2182}
2183
2184/**
2185 * PHY RX end trace
2186 *
2187 * @param context The context.
2188 * @param p The packet.
2189 */
2190void
2191PhyRxDoneTrace(std::string context, Ptr<const Packet> p)
2192{
2193 NS_LOG_INFO("PHY-RX-END time=" << Simulator::Now() << " node=" << ContextToNodeId(context)
2194 << " size=" << p->GetSize());
2195}
2196
2197/**
2198 * PHY successful RX trace
2199 *
2200 * @param context The context.
2201 * @param p The packet.
2202 * @param snr The SNR.
2203 * @param mode The WiFi mode.
2204 * @param preamble The preamble.
2205 */
2206void
2207PhyRxOkTrace(std::string context,
2209 double snr,
2210 WifiMode mode,
2211 WifiPreamble preamble)
2212{
2213 uint8_t nMpdus = (p->GetSize() / pktSize);
2214 NS_LOG_INFO("PHY-RX-OK time=" << Simulator::Now().As(Time::S) << " node="
2215 << ContextToNodeId(context) << " size=" << p->GetSize()
2216 << " nMPDUs=" << +nMpdus << " snr=" << snr << " mode=" << mode
2217 << " preamble=" << preamble);
2218 if ((maxMpdus != 0) && (nMpdus != 0) && (nMpdus != maxMpdus))
2219 {
2220 if (nMpdus > maxMpdus)
2221 {
2222 NS_FATAL_ERROR("A-MPDU settings not properly applied: maximum configured MPDUs is "
2223 << +maxMpdus << " but received an A-MPDU containing " << +nMpdus
2224 << " MPDUs");
2225 }
2226 NS_LOG_WARN("Warning: less MPDUs aggregated in a received A-MPDU ("
2227 << +nMpdus << ") than configured (" << +maxMpdus << ")");
2228 }
2229 if (p->GetSize() >= pktSize) // ignore non-data frames
2230 {
2231 Mac48Address addr = ContextToMac(context);
2233 }
2234}
2235
2236/**
2237 * PHY RX error trace
2238 *
2239 * @param context The context.
2240 * @param p The packet.
2241 * @param snr The SNR.
2242 */
2243void
2244PhyRxErrorTrace(std::string context, Ptr<const Packet> p, double snr)
2245{
2246 NS_LOG_INFO("PHY-RX-ERROR time=" << Simulator::Now() << " node=" << ContextToNodeId(context)
2247 << " size=" << p->GetSize() << " snr=" << snr);
2248 if (p->GetSize() >= pktSize) // ignore non-data frames
2249 {
2250 Mac48Address addr = ContextToMac(context);
2252 }
2253}
2254
2255/**
2256 * PHY TX trace
2257 *
2258 * @param context The context.
2259 * @param p The packet.
2260 * @param txPowerW The TX power.
2261 */
2262void
2263PhyTxTrace(std::string context, Ptr<const Packet> p, double txPowerW)
2264{
2265 NS_LOG_INFO("PHY-TX-START time=" << Simulator::Now() << " node=" << ContextToNodeId(context)
2266 << " size=" << p->GetSize() << " " << txPowerW);
2267 if (tracing)
2268 {
2270 << " size=" << p->GetSize() << " " << txPowerW << std::endl;
2271 }
2272 if (p->GetSize() >= pktSize) // ignore non-data frames
2273 {
2274 Mac48Address addr = ContextToMac(context);
2276 }
2277}
2278
2279/**
2280 * PHY TX end trace.
2281 *
2282 * @param context The context.
2283 * @param p The packet.
2284 */
2285void
2286PhyTxDoneTrace(std::string context, Ptr<const Packet> p)
2287{
2288 NS_LOG_INFO("PHY-TX-END time=" << Simulator::Now() << " node=" << ContextToNodeId(context)
2289 << " " << p->GetSize());
2290}
2291
2292/**
2293 * MAC TX trace.
2294 *
2295 * @param context The context.
2296 * @param p The packet.
2297 */
2298void
2299MacTxTrace(std::string context, Ptr<const Packet> p)
2300{
2301 if (tracing)
2302 {
2303 macTxTraceFile << Simulator::Now().GetSeconds() << " " << ContextToNodeId(context) << " "
2304 << p->GetSize() << std::endl;
2305 }
2306}
2307
2308/**
2309 * MAC RX trace.
2310 *
2311 * @param context The context.
2312 * @param p The packet.
2313 */
2314void
2315MacRxTrace(std::string context, Ptr<const Packet> p)
2316{
2317 if (tracing)
2318 {
2319 macRxTraceFile << Simulator::Now().GetSeconds() << " " << ContextToNodeId(context) << " "
2320 << p->GetSize() << std::endl;
2321 }
2322}
2323
2324/**
2325 * Socket send trace.
2326 *
2327 * @param context The context.
2328 * @param p The packet.
2329 * @param addr destination address.
2330 */
2331void
2332SocketSendTrace(std::string context, Ptr<const Packet> p, const Address& addr)
2333{
2334 if (tracing)
2335 {
2337 << " " << p->GetSize() << " " << addr << std::endl;
2338 }
2339}
2340
2341/**
2342 * Association log trace.
2343 *
2344 * @param context The context.
2345 * @param address The MAC address.
2346 */
2347void
2348AssociationLog(std::string context, Mac48Address address)
2349{
2350 uint32_t nodeId = ContextToNodeId(context);
2351 auto it = associated.find(nodeId);
2352 if (it == associated.end())
2353 {
2354 NS_LOG_DEBUG("Association: time=" << Simulator::Now() << " node=" << nodeId);
2355 associated.insert(it, nodeId);
2356 }
2357 else
2358 {
2359 NS_FATAL_ERROR(nodeId << " is already associated!");
2360 }
2361}
2362
2363/**
2364 * Deassociation log trace.
2365 *
2366 * @param context The context.
2367 * @param address The MAC address.
2368 */
2369void
2370DisassociationLog(std::string context, Mac48Address address)
2371{
2372 uint32_t nodeId = ContextToNodeId(context);
2373 NS_LOG_DEBUG("Disassociation: time=" << Simulator::Now() << " node=" << nodeId);
2374 NS_FATAL_ERROR("Device should not disassociate!");
2375}
2376
2377/**
2378 * Reset the stats.
2379 */
2380void
2382{
2383 bytesReceived.clear();
2384 packetsReceived.clear();
2385 packetsTransmitted.clear();
2386 psduFailed.clear();
2387 psduSucceeded.clear();
2388 phyHeaderFailed.clear();
2389 timeFirstReceived.clear();
2390 timeLastReceived.clear();
2392 rxEventWhileRxing.clear();
2393 rxEventWhileTxing.clear();
2394 rxEventAbortedByTx.clear();
2395}
2396
2397/**
2398 * Class to configure and run an experiment.
2399 */
2401{
2402 public:
2403 Experiment();
2404
2405 /**
2406 * Configure and run the experiment.
2407 *
2408 * @param wifi the pre-configured WifiHelper
2409 * @param wifiPhy the pre-configured YansWifiPhyHelper
2410 * @param wifiMac the pre-configured WifiMacHelper
2411 * @param wifiChannel the pre-configured YansWifiChannelHelper
2412 * @param trialNumber the trial index
2413 * @param networkSize the number of stations
2414 * @param duration the duration of each simulation run
2415 * @param pcap flag to enable/disable PCAP files generation
2416 * @param infra flag to enable infrastructure model, ring adhoc network if not set
2417 * @param guardIntervalNs the guard interval in ns
2418 * @param distance the distance
2419 * @param apTxPower the AP transmit power
2420 * @param staTxPower the STA transmit power
2421 * @param pktInterval the packet interval
2422 * @return 0 if all went well
2423 *
2424 * Call graph was not generated because of its size.
2425 * @hidecallgraph
2426 */
2427 int Run(const WifiHelper& wifi,
2428 const YansWifiPhyHelper& wifiPhy,
2429 const WifiMacHelper& wifiMac,
2430 const YansWifiChannelHelper& wifiChannel,
2431 uint32_t trialNumber,
2432 uint32_t networkSize,
2433 Time duration,
2434 bool pcap,
2435 bool infra,
2436 uint16_t guardIntervalNs,
2437 meter_u distance,
2438 dBm_u apTxPower,
2439 dBm_u staTxPower,
2440 Time pktInterval);
2441};
2442
2446
2447int
2449 const YansWifiPhyHelper& wifiPhy,
2450 const WifiMacHelper& wifiMac,
2451 const YansWifiChannelHelper& wifiChannel,
2452 uint32_t trialNumber,
2453 uint32_t networkSize,
2454 Time duration,
2455 bool pcap,
2456 bool infra,
2457 uint16_t guardIntervalNs,
2458 meter_u distance,
2459 dBm_u apTxPower,
2460 dBm_u staTxPower,
2461 Time pktInterval)
2462{
2465
2466 NodeContainer wifiNodes;
2467 if (infra)
2468 {
2469 wifiNodes.Create(networkSize + 1);
2470 }
2471 else
2472 {
2473 wifiNodes.Create(networkSize);
2474 }
2475
2476 YansWifiPhyHelper phy = wifiPhy;
2477 phy.SetErrorRateModel("ns3::NistErrorRateModel");
2478 phy.SetChannel(wifiChannel.Create());
2479 phy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11_RADIO);
2480
2481 WifiMacHelper mac = wifiMac;
2482 const auto& wifi = helper;
2483 NetDeviceContainer devices;
2484 uint32_t nNodes = wifiNodes.GetN();
2485 if (infra)
2486 {
2487 Ssid ssid = Ssid("wifi-bianchi");
2488 uint64_t beaconInterval = std::min<uint64_t>(
2489 (ceil((duration.GetSeconds() * 1000000) / 1024) * 1024),
2490 (65535 * 1024)); // beacon interval needs to be a multiple of time units (1024 us)
2491 mac.SetType("ns3::ApWifiMac",
2492 "BeaconInterval",
2493 TimeValue(MicroSeconds(beaconInterval)),
2494 "Ssid",
2495 SsidValue(ssid));
2496 phy.Set("TxPowerStart", DoubleValue(apTxPower));
2497 phy.Set("TxPowerEnd", DoubleValue(apTxPower));
2498 devices = wifi.Install(phy, mac, wifiNodes.Get(0));
2499
2500 mac.SetType("ns3::StaWifiMac",
2501 "MaxMissedBeacons",
2502 UintegerValue(std::numeric_limits<uint32_t>::max()),
2503 "Ssid",
2504 SsidValue(ssid));
2505 phy.Set("TxPowerStart", DoubleValue(staTxPower));
2506 phy.Set("TxPowerEnd", DoubleValue(staTxPower));
2507 for (uint32_t i = 1; i < nNodes; ++i)
2508 {
2509 devices.Add(wifi.Install(phy, mac, wifiNodes.Get(i)));
2510 }
2511 }
2512 else
2513 {
2514 mac.SetType("ns3::AdhocWifiMac");
2515 phy.Set("TxPowerStart", DoubleValue(staTxPower));
2516 phy.Set("TxPowerEnd", DoubleValue(staTxPower));
2517 devices = wifi.Install(phy, mac, wifiNodes);
2518 }
2519
2520 WifiHelper::AssignStreams(devices, trialNumber);
2521
2523 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/ShortGuardIntervalSupported",
2524 BooleanValue(guardIntervalNs == 400));
2525 Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HeConfiguration/GuardInterval",
2526 TimeValue(NanoSeconds(guardIntervalNs)));
2527
2528 // Configure aggregation
2529 for (uint32_t i = 0; i < nNodes; ++i)
2530 {
2531 Ptr<NetDevice> dev = wifiNodes.Get(i)->GetDevice(0);
2533 wifi_dev->GetMac()->SetAttribute("BE_MaxAmpduSize",
2534 UintegerValue(maxMpdus * (pktSize + 50)));
2535 wifi_dev->GetMac()->SetAttribute("BK_MaxAmpduSize",
2536 UintegerValue(maxMpdus * (pktSize + 50)));
2537 wifi_dev->GetMac()->SetAttribute("VO_MaxAmpduSize",
2538 UintegerValue(maxMpdus * (pktSize + 50)));
2539 wifi_dev->GetMac()->SetAttribute("VI_MaxAmpduSize",
2540 UintegerValue(maxMpdus * (pktSize + 50)));
2541 }
2542
2543 MobilityHelper mobility;
2545 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
2546 // Set position for AP
2547 positionAlloc->Add(Vector(1.0, 1.0, 0.0));
2548
2549 // Set position for STAs
2550 const auto angle = (static_cast<degree_u>(360) / (nNodes - 1));
2551 for (uint32_t i = 0; i < (nNodes - 1); ++i)
2552 {
2553 positionAlloc->Add(Vector(1.0 + (distance * cos((i * angle * PI) / 180)),
2554 1.0 + (distance * sin((i * angle * PI) / 180)),
2555 0.0));
2556 }
2557
2558 mobility.SetPositionAllocator(positionAlloc);
2559 mobility.Install(wifiNodes);
2560
2561 PacketSocketHelper packetSocket;
2562 packetSocket.Install(wifiNodes);
2563
2566 startTime->SetAttribute("Stream", IntegerValue(trialNumber));
2567 startTime->SetAttribute("Max", DoubleValue(5.0));
2568
2569 uint32_t i = infra ? 1 : 0;
2570 for (; i < nNodes; ++i)
2571 {
2572 uint32_t j = infra ? 0 : (i + 1) % nNodes;
2573 PacketSocketAddress socketAddr;
2574 socketAddr.SetSingleDevice(devices.Get(i)->GetIfIndex());
2575 socketAddr.SetPhysicalAddress(devices.Get(j)->GetAddress());
2576 socketAddr.SetProtocol(1);
2577
2579 client->SetRemote(socketAddr);
2580 wifiNodes.Get(i)->AddApplication(client);
2581 client->SetAttribute("PacketSize", UintegerValue(pktSize));
2582 client->SetAttribute("MaxPackets", UintegerValue(0));
2583 client->SetAttribute("Interval", TimeValue(pktInterval));
2584 double start = startTime->GetValue();
2585 NS_LOG_DEBUG("Client " << i << " starting at " << start);
2586 client->SetStartTime(Seconds(start));
2587
2589 server->SetLocal(socketAddr);
2590 wifiNodes.Get(j)->AddApplication(server);
2591 }
2592
2593 // Log packet receptions
2595 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/MonitorSnifferRx",
2597
2598 // Log association and disassociation
2599 if (infra)
2600 {
2601 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/Assoc",
2603 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/DeAssoc",
2605 }
2606
2607 std::string txop =
2608 StaticCast<WifiNetDevice>(wifiNodes.Get(0)->GetDevice(0))->GetMac()->GetQosSupported()
2609 ? "BE_Txop"
2610 : "Txop";
2611 // Trace CW evolution
2612 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::WifiMac/" + txop +
2613 "/CwTrace",
2615 // Trace backoff evolution
2616 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::WifiMac/" + txop +
2617 "/BackoffTrace",
2619 // Trace PHY Tx start events
2620 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxBegin",
2622 // Trace PHY Tx end events
2623 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxEnd",
2625 // Trace PHY Rx start events
2626 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxBegin",
2628 // Trace PHY Rx payload start events
2630 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxPayloadBegin",
2632 // Trace PHY Rx drop events
2633 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxDrop",
2635 // Trace PHY Rx end events
2636 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxEnd",
2638 // Trace PHY Rx error events
2639 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxError",
2641 // Trace PHY Rx success events
2642 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxOk",
2644 // Trace packet transmission by the device
2645 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx",
2647 // Trace packet receptions to the device
2648 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx",
2650 // Trace packets transmitted by the application
2651 Config::Connect("/NodeList/*/$ns3::Node/ApplicationList/*/$ns3::PacketSocketClient/Tx",
2653
2654 WifiTxStatsHelper wifiTxStats;
2655 if (useTxHelper)
2656 {
2657 // Setup Wi-Fi Transmission Statistics Helper (WifiTxStatsHelper) for all devices
2658 wifiTxStats.Enable(devices);
2659 wifiTxStats.Start(Seconds(10));
2660 wifiTxStats.Stop(Seconds(10) + duration);
2661 }
2662
2663 WifiPhyRxTraceHelper rxTraceHelper;
2664 if (useRxHelper)
2665 {
2666 // Setup Wi-Fi PHY Reception Trace Helper (WifiPhyRxTraceHelper) for all devices
2667 rxTraceHelper.Enable(devices);
2668 rxTraceHelper.Start(Seconds(10));
2669 rxTraceHelper.Stop(Seconds(10) + duration);
2670 }
2671
2673 Simulator::Stop(Seconds(10) + duration);
2674
2675 if (pcap)
2676 {
2677 phy.EnablePcap("wifi_bianchi_pcap", devices);
2678 }
2679
2682
2683 if (useTxHelper)
2684 {
2685 // Get results from WifiTxStatsHelper
2686 const auto numSuccessPerNodeDevice = wifiTxStats.GetSuccessesByNodeDevice();
2687 const auto numFailurePerNodeDevice = wifiTxStats.GetFailuresByNodeDevice();
2688 const auto numFailureDueToFailedEnqueuePerNodeDevice =
2690 const auto numFailureDueToExpiredLifetimePerNodeDevice =
2692 const auto numFailureDueToRetryLimitReachedPerNodeDevice =
2694 const auto numFailureDueToQosOldPacketPerNodeDevice =
2696 const auto numRetransPerNodeDevice = wifiTxStats.GetRetransmissionsByNodeDevice();
2697 std::cout << "WifiTxStatsHelper: node to number of MPDUs acked during (10, "
2698 << 10 + duration.ToInteger(Time::S) << "] s:" << std::endl;
2699 if (numSuccessPerNodeDevice.empty())
2700 {
2701 std::cout << "none\n";
2702 }
2703 else
2704 {
2705 std::cout << std::setw(5) << "node" << std::setw(10) << "nSuccess" << std::endl;
2706 for (const auto& [nodeDevTuple, nSuccess] : numSuccessPerNodeDevice)
2707 {
2708 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nSuccess
2709 << std::endl;
2710 }
2711 }
2712 std::cout
2713 << "WifiTxStatsHelper: node to number of MPDUs failed (due to any reason) during (10, "
2714 << 10 + duration.ToInteger(Time::S) << "] s:" << std::endl;
2715 if (numFailurePerNodeDevice.empty())
2716 {
2717 std::cout << "none\n";
2718 }
2719 else
2720 {
2721 std::cout << std::setw(5) << "node" << std::setw(10) << "nFailed" << std::endl;
2722 for (const auto& [nodeDevTuple, nFailure] : numFailurePerNodeDevice)
2723 {
2724 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nFailure
2725 << std::endl;
2726 }
2727 std::cout << "WifiTxStatsHelper: node to number of MPDUs failed (due to "
2728 "WIFI_MAC_DROP_FAILED_ENQUEUE) during (10, "
2729 << 10 + duration.ToInteger(Time::S) << "] s:" << std::endl;
2730 if (numFailureDueToFailedEnqueuePerNodeDevice.empty())
2731 {
2732 std::cout << "none\n";
2733 }
2734 else
2735 {
2736 std::cout << std::setw(5) << "node" << std::setw(10) << "nFailed" << std::endl;
2737 for (const auto& [nodeDevTuple, nFailure] :
2738 numFailureDueToFailedEnqueuePerNodeDevice)
2739 {
2740 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2741 << nFailure << std::endl;
2742 }
2743 }
2744 std::cout << "WifiTxStatsHelper: node to number of MPDUs failed (due to "
2745 "WIFI_MAC_DROP_EXPIRED_LIFETIME) during (10, "
2746 << 10 + duration.ToInteger(Time::S) << "] s:" << std::endl;
2747 if (numFailureDueToExpiredLifetimePerNodeDevice.empty())
2748 {
2749 std::cout << "none\n";
2750 }
2751 else
2752 {
2753 std::cout << std::setw(5) << "node" << std::setw(10) << "nFailed" << std::endl;
2754 for (const auto& [nodeDevTuple, nFailure] :
2755 numFailureDueToExpiredLifetimePerNodeDevice)
2756 {
2757 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2758 << nFailure << std::endl;
2759 }
2760 }
2761 std::cout << "WifiTxStatsHelper: node to number of MPDUs failed (due to "
2762 "WIFI_MAC_DROP_REACHED_RETRY_LIMIT) during (10, "
2763 << 10 + duration.ToInteger(Time::S) << "] s:" << std::endl;
2764 if (numFailureDueToRetryLimitReachedPerNodeDevice.empty())
2765 {
2766 std::cout << "none\n";
2767 }
2768 else
2769 {
2770 std::cout << std::setw(5) << "node" << std::setw(10) << "nFailed" << std::endl;
2771 for (const auto& [nodeDevTuple, nFailure] :
2772 numFailureDueToRetryLimitReachedPerNodeDevice)
2773 {
2774 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2775 << nFailure << std::endl;
2776 }
2777 }
2778 std::cout << "WifiTxStatsHelper: node to number of MPDUs failed (due to "
2779 "WIFI_MAC_DROP_QOS_OLD_PACKET) during (10, "
2780 << 10 + duration.ToInteger(Time::S) << "] s:" << std::endl;
2781 if (numFailureDueToQosOldPacketPerNodeDevice.empty())
2782 {
2783 std::cout << "none\n";
2784 }
2785 else
2786 {
2787 std::cout << std::setw(5) << "node" << std::setw(10) << "nFailed" << std::endl;
2788 for (const auto& [nodeDevTuple, nFailure] :
2789 numFailureDueToQosOldPacketPerNodeDevice)
2790 {
2791 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2792 << nFailure << std::endl;
2793 }
2794 }
2795 }
2796 std::cout << "WifiTxStatsHelper: node to number of retransmissions of MPDUs "
2797 "Acked during (10, "
2798 << 10 + duration.ToInteger(Time::S) << "] s:" << std::endl;
2799 if (numRetransPerNodeDevice.empty())
2800 {
2801 std::cout << "none\n";
2802 }
2803 else
2804 {
2805 std::cout << std::setw(5) << "node" << std::setw(10) << "nRetrans" << std::endl;
2806 for (const auto& [nodeDevTuple, nRetrans] : numRetransPerNodeDevice)
2807 {
2808 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nRetrans
2809 << std::endl;
2810 }
2811 }
2812 }
2813
2814 if (useRxHelper)
2815 {
2816 // Get results from WifiPhyRxTraceHelper
2817 std::cout << "\nWifiPhyRxTraceHelper: overall statistics" << std::endl;
2818 rxTraceHelper.PrintStatistics();
2819 for (uint32_t nodeIndex = 0; nodeIndex < nNodes; ++nodeIndex)
2820 {
2821 std::cout << "\nWifiPhyRxTraceHelper: per-node statistics for node " << nodeIndex
2822 << std::endl;
2823 rxTraceHelper.PrintStatistics(nodeIndex);
2824 }
2825 std::cout << std::endl;
2826 }
2827
2828 if (tracing)
2829 {
2830 cwTraceFile.flush();
2831 backoffTraceFile.flush();
2832 phyTxTraceFile.flush();
2833 macTxTraceFile.flush();
2834 macRxTraceFile.flush();
2835 socketSendTraceFile.flush();
2836 }
2837
2838 return 0;
2839}
2840
2841/**
2842 * Get the Counter associated with a MAC address.
2843 *
2844 * @param counter The map of counters to inspect.
2845 * @param addr The MAC address.
2846 * @return the value of the counter,
2847 */
2848uint64_t
2849GetCount(const std::map<Mac48Address, uint64_t>& counter, Mac48Address addr)
2850{
2851 uint64_t count = 0;
2852 auto it = counter.find(addr);
2853 if (it != counter.end())
2854 {
2855 count = it->second;
2856 }
2857 return count;
2858}
2859
2860} // unnamed namespace
2861
2862int
2863main(int argc, char* argv[])
2864{
2865 uint32_t nMinStas = 5; ///< Minimum number of STAs to start with
2866 uint32_t nMaxStas = 50; ///< Maximum number of STAs to end with
2867 uint32_t nStepSize = 5; ///< Number of stations to add at each step
2868 uint32_t verbose = 0; ///< verbosity level that increases the number of debugging traces
2869 double duration = 100; ///< duration (in seconds) of each simulation run (i.e. per trial and per
2870 ///< number of stations)
2871 uint32_t trials = 1; ///< Number of runs per point in the plot
2872 bool pcap = false; ///< Flag to enable/disable PCAP files generation
2873 bool infra = false; ///< Flag to enable infrastructure model, ring adhoc network if not set
2874 std::string workDir = "./"; ///< the working directory to store generated files
2875 std::string phyMode =
2876 "OfdmRate54Mbps"; ///< the constant PHY mode string used to transmit frames
2877 std::string standard("11a"); ///< the 802.11 standard
2878 bool validate = false; ///< Flag used for regression in order to verify ns-3 results are in the
2879 ///< expected boundaries
2880 uint16_t plotBianchiModel =
2881 0x01; ///< First bit corresponds to the DIFS model, second bit to the EIFS model
2882 double maxRelativeError =
2883 0.015; ///< Maximum relative error tolerated between ns-3 results and the Bianchi model
2884 ///< (used for regression, i.e. when the validate flag is set)
2885 double frequency = 5; ///< The operating frequency band in GHz: 2.4, 5 or 6
2886 uint16_t channelWidth = 20; ///< The constant channel width in MHz (only for 11n/ac/ax)
2887 uint16_t guardIntervalNs = 800; ///< The guard interval in nanoseconds (800 or 400 for 11n/ac,
2888 ///< 800 or 1600 or 3200 for 11 ax)
2889 uint16_t pktInterval =
2890 1000; ///< The socket packet interval in microseconds (a higher value is needed to reach
2891 ///< saturation conditions as the channel bandwidth or the MCS increases)
2892 meter_u distance = 0.001; ///< The distance in meters between the AP and the STAs
2893 dBm_u apTxPower{16}; ///< The transmit power of the AP (if infrastructure only)
2894 dBm_u staTxPower{16}; ///< The transmit power of each STA (or all STAs if adhoc)
2895
2896 // Disable fragmentation and RTS/CTS
2897 Config::SetDefault("ns3::WifiRemoteStationManager::FragmentationThreshold",
2898 StringValue("22000"));
2899 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue("22000"));
2900 // Make CW stay equal to CWmax until a packet is acknowledged
2901 Config::SetDefault("ns3::WifiMac::FrameRetryLimit", UintegerValue(65535));
2902 // Set maximum queue size to the largest value and set maximum queue delay to be larger than the
2903 // simulation time
2905 "ns3::WifiMacQueue::MaxSize",
2906 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, std::numeric_limits<uint32_t>::max())));
2907 Config::SetDefault("ns3::WifiMacQueue::MaxDelay", TimeValue(Seconds(2 * duration)));
2908
2909 CommandLine cmd(__FILE__);
2910 cmd.AddValue("verbose",
2911 "Logging level (0: no log - 1: simulation script logs - 2: all logs)",
2912 verbose);
2913 cmd.AddValue("tracing", "Generate trace files", tracing);
2914 cmd.AddValue("useTxHelper", "Enable WifiTxStatsHelper on all devices", useTxHelper);
2915 cmd.AddValue("useRxHelper", "Enable WifiPhyRxTraceHelper on all devices", useRxHelper);
2916 cmd.AddValue("pktSize", "The packet size in bytes", pktSize);
2917 cmd.AddValue("trials", "The maximal number of runs per network size", trials);
2918 cmd.AddValue("duration", "Time duration for each trial in seconds", duration);
2919 cmd.AddValue("pcap", "Enable/disable PCAP tracing", pcap);
2920 cmd.AddValue("infra", "True to use infrastructure mode, false to use ring adhoc mode", infra);
2921 cmd.AddValue("workDir", "The working directory used to store generated files", workDir);
2922 cmd.AddValue("phyMode", "Set the constant PHY mode string used to transmit frames", phyMode);
2923 cmd.AddValue("standard", "Set the standard (11a, 11b, 11g, 11n, 11ac, 11ax)", standard);
2924 cmd.AddValue("nMinStas", "Minimum number of stations to start with", nMinStas);
2925 cmd.AddValue("nMaxStas", "Maximum number of stations to start with", nMaxStas);
2926 cmd.AddValue("nStepSize", "Number of stations to add at each step", nStepSize);
2927 cmd.AddValue("plotBianchiModel",
2928 "First bit corresponds to the DIFS model, second bit to the EIFS model",
2929 plotBianchiModel);
2930 cmd.AddValue("validate",
2931 "Enable/disable validation of the ns-3 simulations against the Bianchi model",
2932 validate);
2933 cmd.AddValue("maxRelativeError",
2934 "The maximum relative error tolerated between ns-3 results and the Bianchi model "
2935 "(used for regression, i.e. when the validate flag is set)",
2936 maxRelativeError);
2937 cmd.AddValue("frequency", "Set the operating frequency band in GHz: 2.4, 5 or 6", frequency);
2938 cmd.AddValue("channelWidth",
2939 "Set the constant channel width in MHz (only for 11n/ac/ax)",
2940 channelWidth);
2941 cmd.AddValue("guardIntervalNs",
2942 "Set the the guard interval in nanoseconds (800 or 400 for 11n/ac, 800 or 1600 or "
2943 "3200 for 11 ax)",
2944 guardIntervalNs);
2945 cmd.AddValue("maxMpdus",
2946 "Set the maximum number of MPDUs in A-MPDUs (0 to disable MPDU aggregation)",
2947 maxMpdus);
2948 cmd.AddValue("distance", "Set the distance in meters between the AP and the STAs", distance);
2949 cmd.AddValue("apTxPower",
2950 "Set the transmit power of the AP in dBm (if infrastructure only)",
2951 apTxPower);
2952 cmd.AddValue("staTxPower",
2953 "Set the transmit power of each STA in dBm (or all STAs if adhoc)",
2954 staTxPower);
2955 cmd.AddValue("pktInterval", "Set the socket packet interval in microseconds", pktInterval);
2956 cmd.Parse(argc, argv);
2957
2958 if (tracing)
2959 {
2960 cwTraceFile.open("wifi-bianchi-cw-trace.out");
2961 if (!cwTraceFile.is_open())
2962 {
2963 NS_FATAL_ERROR("Failed to open file wifi-bianchi-cw-trace.out");
2964 }
2965 backoffTraceFile.open("wifi-bianchi-backoff-trace.out");
2966 if (!backoffTraceFile.is_open())
2967 {
2968 NS_FATAL_ERROR("Failed to open file wifi-bianchi-backoff-trace.out");
2969 }
2970 phyTxTraceFile.open("wifi-bianchi-phy-tx-trace.out");
2971 if (!phyTxTraceFile.is_open())
2972 {
2973 NS_FATAL_ERROR("Failed to open file wifi-bianchi-phy-tx-trace.out");
2974 }
2975 macTxTraceFile.open("wifi-bianchi-mac-tx-trace.out");
2976 if (!macTxTraceFile.is_open())
2977 {
2978 NS_FATAL_ERROR("Failed to open file wifi-bianchi-mac-tx-trace.out");
2979 }
2980 macRxTraceFile.open("wifi-bianchi-mac-rx-trace.out");
2981 if (!macRxTraceFile.is_open())
2982 {
2983 NS_FATAL_ERROR("Failed to open file wifi-bianchi-mac-rx-trace.out");
2984 }
2985 socketSendTraceFile.open("wifi-bianchi-socket-send-trace.out");
2986 if (!socketSendTraceFile.is_open())
2987 {
2988 NS_FATAL_ERROR("Failed to open file wifi-bianchi-socket-send-trace.out");
2989 }
2990 }
2991
2992 if (verbose >= 1)
2993 {
2994 LogComponentEnable("WifiBianchi", LOG_LEVEL_ALL);
2995 }
2996 else
2997 {
2998 LogComponentEnable("WifiBianchi", LOG_LEVEL_WARN);
2999 }
3000 if (verbose >= 2)
3001 {
3003 }
3004
3005 std::stringstream phyModeStr;
3006 phyModeStr << phyMode;
3007 if (phyMode.find("Mcs") != std::string::npos)
3008 {
3009 phyModeStr << "_" << channelWidth << "MHz";
3010 }
3011
3012 std::stringstream ss;
3013 ss << "wifi-" << standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") << "-r-"
3014 << phyModeStr.str() << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize
3015 << "-throughput.plt";
3016 std::ofstream throughputPlot(ss.str());
3017 ss.str("");
3018 ss << "wifi-" << standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") << "-r-"
3019 << phyModeStr.str() << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize
3020 << "-throughput.eps";
3021 Gnuplot gnuplot = Gnuplot(ss.str());
3022
3023 WifiStandard wifiStandard;
3024 if (standard == "11a")
3025 {
3026 wifiStandard = WIFI_STANDARD_80211a;
3027 frequency = 5;
3028 channelWidth = 20;
3029 }
3030 else if (standard == "11b")
3031 {
3032 wifiStandard = WIFI_STANDARD_80211b;
3033 frequency = 2.4;
3034 channelWidth = 22;
3035 }
3036 else if (standard == "11g")
3037 {
3038 wifiStandard = WIFI_STANDARD_80211g;
3039 frequency = 2.4;
3040 channelWidth = 20;
3041 }
3042 else if (standard == "11n")
3043 {
3044 if (frequency == 2.4 || frequency == 5)
3045 {
3046 wifiStandard = WIFI_STANDARD_80211n;
3047 }
3048 else
3049 {
3050 NS_FATAL_ERROR("Unsupported frequency band " << frequency << " GHz for standard "
3051 << standard);
3052 }
3053 }
3054 else if (standard == "11ac")
3055 {
3056 wifiStandard = WIFI_STANDARD_80211ac;
3057 frequency = 5;
3058 }
3059 else if (standard == "11ax")
3060 {
3061 if (frequency == 2.4 || frequency == 5 || frequency == 6)
3062 {
3063 wifiStandard = WIFI_STANDARD_80211ax;
3064 }
3065 else
3066 {
3067 NS_FATAL_ERROR("Unsupported frequency band " << frequency << " GHz for standard "
3068 << standard);
3069 }
3070 }
3071 else
3072 {
3073 NS_FATAL_ERROR("Unsupported standard: " << standard);
3074 }
3075
3076 std::string channelStr = "{0, " + std::to_string(channelWidth) + ", BAND_" +
3077 (frequency == 2.4 ? "2_4" : (frequency == 5 ? "5" : "6")) + "GHZ, 0}";
3078 Config::SetDefault("ns3::WifiPhy::ChannelSettings", StringValue(channelStr));
3079
3080 YansWifiPhyHelper wifiPhy;
3082
3083 YansWifiChannelHelper wifiChannel;
3084 wifiChannel.SetPropagationDelay("ns3::ConstantSpeedPropagationDelayModel");
3085 if (frequency == 6)
3086 {
3087 // Reference Loss for Friss at 1 m with 6.0 GHz
3088 wifiChannel.AddPropagationLoss("ns3::LogDistancePropagationLossModel",
3089 "Exponent",
3090 DoubleValue(2.0),
3091 "ReferenceDistance",
3092 DoubleValue(1.0),
3093 "ReferenceLoss",
3094 DoubleValue(49.013));
3095 }
3096 else if (frequency == 5)
3097 {
3098 // Reference Loss for Friss at 1 m with 5.15 GHz
3099 wifiChannel.AddPropagationLoss("ns3::LogDistancePropagationLossModel",
3100 "Exponent",
3101 DoubleValue(2.0),
3102 "ReferenceDistance",
3103 DoubleValue(1.0),
3104 "ReferenceLoss",
3105 DoubleValue(46.6777));
3106 }
3107 else
3108 {
3109 // Reference Loss for Friss at 1 m with 2.4 GHz
3110 wifiChannel.AddPropagationLoss("ns3::LogDistancePropagationLossModel",
3111 "Exponent",
3112 DoubleValue(2.0),
3113 "ReferenceDistance",
3114 DoubleValue(1.0),
3115 "ReferenceLoss",
3116 DoubleValue(40.046));
3117 }
3118
3120 wifi.SetStandard(wifiStandard);
3121 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
3122 "DataMode",
3123 StringValue(phyMode),
3124 "ControlMode",
3125 StringValue(phyMode));
3126
3127 Gnuplot2dDataset dataset;
3128 Gnuplot2dDataset datasetBianchiEifs;
3129 Gnuplot2dDataset datasetBianchiDifs;
3132 datasetBianchiEifs.SetStyle(Gnuplot2dDataset::LINES_POINTS);
3133 datasetBianchiDifs.SetStyle(Gnuplot2dDataset::LINES_POINTS);
3134
3136 WifiMacHelper wifiMac;
3137 double averageThroughput;
3138 std::vector<double> throughputArray(trials);
3139 for (uint32_t n = nMinStas; n <= nMaxStas; n += nStepSize)
3140 {
3141 averageThroughput = 0;
3142 double throughput;
3143 for (uint32_t runIndex = 0; runIndex < trials; runIndex++)
3144 {
3145 packetsReceived.clear();
3146 bytesReceived.clear();
3147 packetsTransmitted.clear();
3148 psduFailed.clear();
3149 psduSucceeded.clear();
3150 phyHeaderFailed.clear();
3151 timeFirstReceived.clear();
3152 timeLastReceived.clear();
3154 rxEventWhileRxing.clear();
3155 rxEventWhileTxing.clear();
3156 rxEventAbortedByTx.clear();
3157 associated.clear();
3158 throughput = 0;
3159 std::cout << "Trial " << runIndex + 1 << " of " << trials << "; " << phyModeStr.str()
3160 << " for " << n << " nodes " << std::endl;
3161 if (tracing)
3162 {
3163 cwTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
3164 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
3165 backoffTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
3166 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
3167 phyTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
3168 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
3169 macTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
3170 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
3171 macRxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
3172 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
3173 socketSendTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
3174 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
3175 }
3176 experiment.Run(wifi,
3177 wifiPhy,
3178 wifiMac,
3179 wifiChannel,
3180 runIndex,
3181 n,
3182 Seconds(duration),
3183 pcap,
3184 infra,
3185 guardIntervalNs,
3186 distance,
3187 apTxPower,
3188 staTxPower,
3189 MicroSeconds(pktInterval));
3190 uint32_t k = 0;
3191 if (bytesReceived.size() != n)
3192 {
3193 NS_FATAL_ERROR("Not all stations got traffic!");
3194 }
3195 for (auto it = bytesReceived.begin(); it != bytesReceived.end(); it++, k++)
3196 {
3197 Time first = timeFirstReceived.find(it->first)->second;
3198 Time last = timeLastReceived.find(it->first)->second;
3199 Time dataTransferDuration = last - first;
3200 double nodeThroughput =
3201 (it->second * 8 / static_cast<double>(dataTransferDuration.GetMicroSeconds()));
3202 throughput += nodeThroughput;
3203 uint64_t nodeTxPackets = GetCount(packetsTransmitted, it->first);
3204 uint64_t nodeRxPackets = GetCount(packetsReceived, it->first);
3205 uint64_t nodePhyHeaderFailures = GetCount(phyHeaderFailed, it->first);
3206 uint64_t nodePsduFailures = GetCount(psduFailed, it->first);
3207 uint64_t nodePsduSuccess = GetCount(psduSucceeded, it->first);
3208 uint64_t nodeRxEventWhileDecodingPreamble =
3210 uint64_t nodeRxEventWhileRxing = GetCount(rxEventWhileRxing, it->first);
3211 uint64_t nodeRxEventWhileTxing = GetCount(rxEventWhileTxing, it->first);
3212 uint64_t nodeRxEventAbortedByTx = GetCount(rxEventAbortedByTx, it->first);
3213 uint64_t nodeRxEvents = nodePhyHeaderFailures + nodePsduFailures + nodePsduSuccess +
3214 nodeRxEventWhileDecodingPreamble + nodeRxEventWhileRxing +
3215 nodeRxEventWhileTxing + nodeRxEventAbortedByTx;
3216 std::cout << "Node " << it->first << ": TX packets " << nodeTxPackets
3217 << "; RX packets " << nodeRxPackets << "; PHY header failures "
3218 << nodePhyHeaderFailures << "; PSDU failures " << nodePsduFailures
3219 << "; PSDU success " << nodePsduSuccess
3220 << "; RX events while decoding preamble "
3221 << nodeRxEventWhileDecodingPreamble << "; RX events while RXing "
3222 << nodeRxEventWhileRxing << "; RX events while TXing "
3223 << nodeRxEventWhileTxing << "; RX events aborted by TX "
3224 << nodeRxEventAbortedByTx << "; total RX events " << nodeRxEvents
3225 << "; total events " << nodeTxPackets + nodeRxEvents << "; time first RX "
3226 << first << "; time last RX " << last << "; dataTransferDuration "
3227 << dataTransferDuration << "; throughput " << nodeThroughput << " Mbps"
3228 << std::endl;
3229 }
3230 std::cout << "Total throughput: " << throughput << " Mbps" << std::endl;
3231 averageThroughput += throughput;
3232 throughputArray[runIndex] = throughput;
3233 }
3234 averageThroughput = averageThroughput / trials;
3235
3236 bool rateFound = false;
3237 double relativeErrorDifs = 0;
3238 double relativeErrorEifs = 0;
3239 auto itDifs = bianchiResultsDifs.find(phyModeStr.str());
3240 if (itDifs != bianchiResultsDifs.end())
3241 {
3242 rateFound = true;
3243 auto it = itDifs->second.find(n);
3244 if (it != itDifs->second.end())
3245 {
3246 relativeErrorDifs = (std::abs(averageThroughput - it->second) / it->second);
3247 std::cout << "Relative error (DIFS): " << 100 * relativeErrorDifs << "%"
3248 << std::endl;
3249 }
3250 else if (validate)
3251 {
3252 NS_FATAL_ERROR("No Bianchi results (DIFS) calculated for that number of stations!");
3253 }
3254 }
3255 auto itEifs = bianchiResultsEifs.find(phyModeStr.str());
3256 if (itEifs != bianchiResultsEifs.end())
3257 {
3258 rateFound = true;
3259 auto it = itEifs->second.find(n);
3260 if (it != itEifs->second.end())
3261 {
3262 relativeErrorEifs = (std::abs(averageThroughput - it->second) / it->second);
3263 std::cout << "Relative error (EIFS): " << 100 * relativeErrorEifs << "%"
3264 << std::endl;
3265 }
3266 else if (validate)
3267 {
3268 NS_FATAL_ERROR("No Bianchi results (EIFS) calculated for that number of stations!");
3269 }
3270 }
3271 if (!rateFound && validate)
3272 {
3273 NS_FATAL_ERROR("No Bianchi results calculated for that rate!");
3274 }
3275 double relativeError = std::min(relativeErrorDifs, relativeErrorEifs);
3276 if (validate && (relativeError > maxRelativeError))
3277 {
3278 NS_FATAL_ERROR("Relative error is too high!");
3279 }
3280
3281 double stDev = 0;
3282 for (uint32_t i = 0; i < trials; ++i)
3283 {
3284 stDev += pow(throughputArray[i] - averageThroughput, 2);
3285 }
3286 stDev = sqrt(stDev / (trials - 1));
3287 dataset.Add(n, averageThroughput, stDev);
3288 }
3289 dataset.SetTitle("ns-3");
3290
3291 auto itDifs = bianchiResultsDifs.find(phyModeStr.str());
3292 if (itDifs != bianchiResultsDifs.end())
3293 {
3294 for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3295 {
3296 double value = 0.0;
3297 auto it = itDifs->second.find(i);
3298 if (it != itDifs->second.end())
3299 {
3300 value = it->second;
3301 }
3302 datasetBianchiDifs.Add(i, value);
3303 }
3304 }
3305 else
3306 {
3307 for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3308 {
3309 datasetBianchiDifs.Add(i, 0.0);
3310 }
3311 }
3312
3313 auto itEifs = bianchiResultsEifs.find(phyModeStr.str());
3314 if (itEifs != bianchiResultsEifs.end())
3315 {
3316 for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3317 {
3318 double value = 0.0;
3319 auto it = itEifs->second.find(i);
3320 if (it != itEifs->second.end())
3321 {
3322 value = it->second;
3323 }
3324 datasetBianchiEifs.Add(i, value);
3325 }
3326 }
3327 else
3328 {
3329 for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3330 {
3331 datasetBianchiEifs.Add(i, 0.0);
3332 }
3333 }
3334
3335 datasetBianchiEifs.SetTitle("Bianchi (EIFS - lower bound)");
3336 datasetBianchiDifs.SetTitle("Bianchi (DIFS - upper bound)");
3337 gnuplot.AddDataset(dataset);
3338 gnuplot.SetTerminal("postscript eps color enh \"Times-BoldItalic\"");
3339 gnuplot.SetLegend("Number of competing stations", "Throughput (Mbps)");
3340 ss.str("");
3341 ss << "Frame size " << pktSize << " bytes";
3342 gnuplot.SetTitle(ss.str());
3343 ss.str("");
3344 ss << "set xrange [" << nMinStas << ":" << nMaxStas << "]\n"
3345 << "set xtics " << nStepSize << "\n"
3346 << "set grid xtics ytics\n"
3347 << "set mytics\n"
3348 << "set style line 1 linewidth 5\n"
3349 << "set style line 2 linewidth 5\n"
3350 << "set style line 3 linewidth 5\n"
3351 << "set style line 4 linewidth 5\n"
3352 << "set style line 5 linewidth 5\n"
3353 << "set style line 6 linewidth 5\n"
3354 << "set style line 7 linewidth 5\n"
3355 << "set style line 8 linewidth 5\n"
3356 << "set style increment user";
3357 gnuplot.SetExtra(ss.str());
3358 if (plotBianchiModel & 0x0001)
3359 {
3360 datasetBianchiDifs.SetTitle("Bianchi");
3361 gnuplot.AddDataset(datasetBianchiDifs);
3362 }
3363 if (plotBianchiModel & 0x0002)
3364 {
3365 datasetBianchiEifs.SetTitle("Bianchi");
3366 gnuplot.AddDataset(datasetBianchiEifs);
3367 }
3368 if (plotBianchiModel == 0x0003)
3369 {
3370 datasetBianchiEifs.SetTitle("Bianchi (EIFS - lower bound)");
3371 datasetBianchiDifs.SetTitle("Bianchi (DIFS - upper bound)");
3372 }
3373 gnuplot.GenerateOutput(throughputPlot);
3374 throughputPlot.close();
3375
3376 if (tracing)
3377 {
3378 cwTraceFile.close();
3379 backoffTraceFile.close();
3380 phyTxTraceFile.close();
3381 macTxTraceFile.close();
3382 macRxTraceFile.close();
3383 socketSendTraceFile.close();
3384 }
3385
3386 return 0;
3387}
Gnuplot2dDataset Run(const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel)
Run an experiment.
int Run(const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel, uint32_t trialNumber, uint32_t networkSize, Time duration, bool pcap, bool infra, uint16_t guardIntervalNs, meter_u distance, dBm_u apTxPower, dBm_u staTxPower, Time pktInterval)
Configure and run the experiment.
a polymophic address class
Definition address.h:114
Headers for A-MPDU subframes.
uint16_t GetLength() const
Return the length field.
holds a vector of ns3::Application pointers.
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 SetErrorBars(ErrorBars errorBars)
Definition gnuplot.cc:360
void SetStyle(Style style)
Definition gnuplot.cc:348
void Add(double x, double y)
Definition gnuplot.cc:366
void SetTitle(const std::string &title)
Change line title.
Definition gnuplot.cc:137
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 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
Hold a signed integer type.
Definition integer.h:34
an EUI-48 address
static Mac48Address ConvertFrom(const Address &address)
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
uint32_t GetN() const
Get the number of Ptr<Node> stored in this container.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition node.cc:153
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition node.cc:138
static Ptr< Node > GetNode(uint32_t n)
Definition node-list.cc:240
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:70
Class for representing queue sizes.
Definition queue-size.h:85
AttributeValue implementation for QueueSize.
Definition queue-size.h:210
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:580
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:125
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
static void Run()
Run the simulation.
Definition simulator.cc:161
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:169
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
AttributeValue implementation for Ssid.
Definition ssid.h:85
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:399
@ S
second
Definition nstime.h:107
int64_t ToInteger(Unit unit) const
Get the Time value expressed in a particular unit.
Definition nstime.h:569
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:409
AttributeValue implementation for Time.
Definition nstime.h:1483
Hold an unsigned integer type.
Definition uinteger.h:34
helps to create WifiNetDevice objects
static void EnableLogComponents(LogLevel logLevel=LOG_LEVEL_ALL)
Helper to enable all WifiNetDevice log components with one statement.
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 ...
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
create MAC layers for a ns3::WifiNetDevice.
represent a single transmission mode
Definition wifi-mode.h:38
Hold together all Wifi-related objects.
void DisablePreambleDetectionModel()
Disable the preamble detection model on all links.
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
Assists in tracing and analyzing Wi-Fi Physical Layer (PHY) receptions.
void PrintStatistics() const
Print statistics for all nodes, devices, and links during the collection period.
void Stop(Time stopTime)
Stops the collection of statistics at a specified time.
void Enable(NodeContainer nodes)
Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
void Start(Time startTime)
Starts the collection of statistics from a specified start time.
Statistics helper for tracking outcomes of data MPDU transmissions.
void Stop(Time stopTime)
Set the stop time for statistics collection.
CountPerNodeDevice_t GetFailuresByNodeDevice() const
Return the counts of failed MPDU transmissions in a hash map.
CountPerNodeDevice_t GetSuccessesByNodeDevice() const
Return the counts of successful MPDU transmissions in a hash map.
void Enable(const NodeContainer &nodes)
Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
CountPerNodeDevice_t GetRetransmissionsByNodeDevice() const
Return the counts of MPDU retransmissions in a hash map.
void Start(Time startTime)
Set the start time for statistics collection.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
bool IsAggregation() const
Checks whether the PSDU contains A-MPDU.
manage and create wifi channel objects for the YANS model.
void SetPropagationDelay(std::string name, Ts &&... args)
void AddPropagationLoss(std::string name, Ts &&... args)
Ptr< YansWifiChannel > Create() const
Make it easy to create and manage PHY objects for the YANS model.
void experiment(std::string queue_disc_type)
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:690
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:886
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:970
void Set(std::string path, const AttributeValue &value)
Definition config.cc:872
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:253
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:267
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
@ PACKETS
Use number of packets for queue size.
Definition queue-size.h:34
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1415
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1432
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211g
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ WIFI_STANDARD_80211b
@ OBSS_PD_CCA_RESET
@ PREAMBLE_DETECT_FAILURE
@ FRAME_CAPTURE_PACKET_SWITCH
@ UNSUPPORTED_SETTINGS
@ L_SIG_FAILURE
@ SIGNAL_DETECTION_ABORTED_BY_TX
@ RECEPTION_ABORTED_BY_TX
@ SIG_A_FAILURE
@ CHANNEL_SWITCHING
@ BUSY_DECODING_PREAMBLE
@ SIG_B_FAILURE
@ HT_SIG_FAILURE
@ PREAMBLE_DETECTION_PACKET_SWITCH
@ WIFI_MAC_DROP_QOS_OLD_PACKET
Definition wifi-mac.h:75
@ WIFI_MAC_DROP_FAILED_ENQUEUE
Definition wifi-mac.h:72
@ WIFI_MAC_DROP_EXPIRED_LIFETIME
Definition wifi-mac.h:73
@ WIFI_MAC_DROP_REACHED_RETRY_LIMIT
Definition wifi-mac.h:74
std::ofstream socketSendTraceFile
File that traces packets transmitted by the application over time.
bool tracing
Flag to enable/disable generation of tracing files.
uint8_t maxMpdus
The maximum number of MPDUs in A-MPDUs (0 to disable MPDU aggregation).
Mac48Address ContextToMac(std::string context)
Parse context strings of the form "/NodeList/x/DeviceList/x/..." and fetch the Mac address.
std::map< Mac48Address, uint64_t > rxEventWhileDecodingPreamble
Map that stores the number of reception events per STA that occurred while PHY was already decoding a...
std::ofstream macTxTraceFile
File that traces MAC transmissions over time.
std::map< Mac48Address, uint64_t > rxEventWhileTxing
Map that stores the number of reception events per STA that occurred while PHY was already transmitti...
std::ofstream cwTraceFile
File that traces CW over time.
std::set< uint32_t > associated
Contains the IDs of the STAs that successfully associated to the access point (in infrastructure mode...
std::map< Mac48Address, uint64_t > packetsTransmitted
Map that stores the total packets transmitted per STA.
void PhyTxDoneTrace(std::string context, Ptr< const Packet > p)
PHY TX end trace.
uint32_t pktSize
packet size used for the simulation (in bytes)
bool useRxHelper
Flag to get PPDU statistics with WifiPhyRxTraceHelper.
std::map< Mac48Address, uint64_t > bytesReceived
Map that stores the total bytes received per STA (and addressed to that STA).
std::map< Mac48Address, uint64_t > packetsReceived
Map that stores the total packets received per STA (and addressed to that STA).
void TracePacketReception(std::string context, Ptr< const Packet > p, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise, uint16_t staId)
Trace a packet reception.
uint32_t ContextToNodeId(std::string context)
Parse context strings of the form "/NodeList/x/DeviceList/x/..." to extract the NodeId integer.
void AssociationLog(std::string context, Mac48Address address)
Association log trace.
void PhyRxTrace(std::string context, Ptr< const Packet > p, RxPowerWattPerChannelBand power)
PHY Rx trace.
void PhyRxErrorTrace(std::string context, Ptr< const Packet > p, double snr)
PHY RX error trace.
void PhyRxOkTrace(std::string context, Ptr< const Packet > p, double snr, WifiMode mode, WifiPreamble preamble)
PHY successful RX trace.
std::map< Mac48Address, uint64_t > phyHeaderFailed
Map that stores the total number of unsuccessfully received PHY headers per STA.
std::map< Mac48Address, Time > timeFirstReceived
Map that stores the time at which the first packet was received per STA (and the packet is addressed ...
std::ofstream backoffTraceFile
File that traces backoff over time.
void DisassociationLog(std::string context, Mac48Address address)
Deassociation log trace.
std::map< Mac48Address, uint64_t > rxEventWhileRxing
Map that stores the number of reception events per STA that occurred while PHY was already receiving ...
void PhyRxDoneTrace(std::string context, Ptr< const Packet > p)
PHY RX end trace.
void PhyTxTrace(std::string context, Ptr< const Packet > p, double txPowerW)
PHY TX trace.
std::map< Mac48Address, uint64_t > psduFailed
Map that stores the total number of unsuccessfully received PSDUS (for which the PHY header was succe...
std::map< Mac48Address, uint64_t > rxEventAbortedByTx
Map that stores the number of reception events aborted per STA because the PHY has started to transmi...
void CwTrace(std::string context, uint32_t cw, uint8_t)
Contention window trace.
std::map< std::string, std::map< unsigned int, double > > bianchiResultsEifs
Table of the expected values for EIFS.
uint64_t GetCount(const std::map< Mac48Address, uint64_t > &counter, Mac48Address addr)
Get the Counter associated with a MAC address.
void IncrementCounter(std::map< Mac48Address, uint64_t > &counter, Mac48Address addr, uint64_t increment=1)
Increment the counter for a given address.
bool useTxHelper
Flag to get MPDU statistics with WifiTxStatsHelper.
std::ofstream phyTxTraceFile
File that traces PHY transmissions over time.
std::map< Mac48Address, Time > timeLastReceived
Map that stores the time at which the last packet was received per STA (and the packet is addressed t...
std::map< std::string, std::map< unsigned int, double > > bianchiResultsDifs
Table of the expected values for DIFS.
void MacTxTrace(std::string context, Ptr< const Packet > p)
MAC TX trace.
void SocketSendTrace(std::string context, Ptr< const Packet > p, const Address &addr)
Socket send trace.
std::ofstream macRxTraceFile
File that traces MAC receptions over time.
std::map< Mac48Address, uint64_t > psduSucceeded
Map that stores the total number of successfully received PSDUs per STA (including PSDUs not addresse...
void MacRxTrace(std::string context, Ptr< const Packet > p)
MAC RX trace.
void PhyRxPayloadTrace(std::string context, WifiTxVector txVector, Time psduDuration)
PHY Rx trace.
std::map< Mac48Address, Time > timeLastTransmitted
Map that stores the time at which the last packet was transmitted per STA.
std::map< Mac48Address, Time > timeFirstTransmitted
Map that stores the time at which the first packet was transmitted per STA.
void PhyRxDropTrace(std::string context, Ptr< const Packet > p, WifiPhyRxfailureReason reason)
PHY Drop trace.
void BackoffTrace(std::string context, uint32_t newVal, uint8_t)
Backoff trace.
Definition first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition log.cc:279
std::map< WifiSpectrumBandInfo, Watt_u > RxPowerWattPerChannelBand
A map of the received power for each band.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:605
double dBm_u
dBm weak type
Definition wifi-units.h:27
@ LOG_LEVEL_ALL
Print everything.
Definition log.h:108
@ LOG_LEVEL_WARN
LOG_WARN and above.
Definition log.h:93
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:612
double degree_u
degree weak type (angle)
Definition wifi-units.h:35
double meter_u
meter weak type
Definition wifi-units.h:32
value
Definition second.py:37
wifi
Definition third.py:84
uint32_t bytesReceived
Counter of the received bytes.
bool verbose
MpduInfo structure.
Definition wifi-types.h:77
SignalNoiseDbm structure.
Definition wifi-types.h:70
std::ofstream throughput
#define PI
Avoid std::numbers::pi because it's C++20.