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