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 // Disable short retransmission failure (make retransmissions persistent)
2717 Config::SetDefault("ns3::WifiRemoteStationManager::MaxSlrc",
2718 UintegerValue(std::numeric_limits<uint32_t>::max()));
2719 Config::SetDefault("ns3::WifiRemoteStationManager::MaxSsrc",
2720 UintegerValue(std::numeric_limits<uint32_t>::max()));
2721 // Set maximum queue size to the largest value and set maximum queue delay to be larger than the
2722 // simulation time
2724 "ns3::WifiMacQueue::MaxSize",
2725 QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, std::numeric_limits<uint32_t>::max())));
2726 Config::SetDefault("ns3::WifiMacQueue::MaxDelay", TimeValue(Seconds(2 * duration)));
2727
2728 CommandLine cmd(__FILE__);
2729 cmd.AddValue("verbose",
2730 "Logging level (0: no log - 1: simulation script logs - 2: all logs)",
2731 verbose);
2732 cmd.AddValue("tracing", "Generate trace files", tracing);
2733 cmd.AddValue("pktSize", "The packet size in bytes", pktSize);
2734 cmd.AddValue("trials", "The maximal number of runs per network size", trials);
2735 cmd.AddValue("duration", "Time duration for each trial in seconds", duration);
2736 cmd.AddValue("pcap", "Enable/disable PCAP tracing", pcap);
2737 cmd.AddValue("infra", "True to use infrastructure mode, false to use ring adhoc mode", infra);
2738 cmd.AddValue("workDir", "The working directory used to store generated files", workDir);
2739 cmd.AddValue("phyMode", "Set the constant PHY mode string used to transmit frames", phyMode);
2740 cmd.AddValue("standard", "Set the standard (11a, 11b, 11g, 11n, 11ac, 11ax)", standard);
2741 cmd.AddValue("nMinStas", "Minimum number of stations to start with", nMinStas);
2742 cmd.AddValue("nMaxStas", "Maximum number of stations to start with", nMaxStas);
2743 cmd.AddValue("nStepSize", "Number of stations to add at each step", nStepSize);
2744 cmd.AddValue("plotBianchiModel",
2745 "First bit corresponds to the DIFS model, second bit to the EIFS model",
2746 plotBianchiModel);
2747 cmd.AddValue("validate",
2748 "Enable/disable validation of the ns-3 simulations against the Bianchi model",
2749 validate);
2750 cmd.AddValue("maxRelativeError",
2751 "The maximum relative error tolerated between ns-3 results and the Bianchi model "
2752 "(used for regression, i.e. when the validate flag is set)",
2753 maxRelativeError);
2754 cmd.AddValue("frequency", "Set the operating frequency band in GHz: 2.4, 5 or 6", frequency);
2755 cmd.AddValue("channelWidth",
2756 "Set the constant channel width in MHz (only for 11n/ac/ax)",
2757 channelWidth);
2758 cmd.AddValue("guardIntervalNs",
2759 "Set the the guard interval in nanoseconds (800 or 400 for 11n/ac, 800 or 1600 or "
2760 "3200 for 11 ax)",
2761 guardIntervalNs);
2762 cmd.AddValue("maxMpdus",
2763 "Set the maximum number of MPDUs in A-MPDUs (0 to disable MPDU aggregation)",
2764 maxMpdus);
2765 cmd.AddValue("distance", "Set the distance in meters between the AP and the STAs", distance);
2766 cmd.AddValue("apTxPower",
2767 "Set the transmit power of the AP in dBm (if infrastructure only)",
2768 apTxPower);
2769 cmd.AddValue("staTxPower",
2770 "Set the transmit power of each STA in dBm (or all STAs if adhoc)",
2771 staTxPower);
2772 cmd.AddValue("pktInterval", "Set the socket packet interval in microseconds", pktInterval);
2773 cmd.Parse(argc, argv);
2774
2775 if (tracing)
2776 {
2777 cwTraceFile.open("wifi-bianchi-cw-trace.out");
2778 if (!cwTraceFile.is_open())
2779 {
2780 NS_FATAL_ERROR("Failed to open file wifi-bianchi-cw-trace.out");
2781 }
2782 backoffTraceFile.open("wifi-bianchi-backoff-trace.out");
2783 if (!backoffTraceFile.is_open())
2784 {
2785 NS_FATAL_ERROR("Failed to open file wifi-bianchi-backoff-trace.out");
2786 }
2787 phyTxTraceFile.open("wifi-bianchi-phy-tx-trace.out");
2788 if (!phyTxTraceFile.is_open())
2789 {
2790 NS_FATAL_ERROR("Failed to open file wifi-bianchi-phy-tx-trace.out");
2791 }
2792 macTxTraceFile.open("wifi-bianchi-mac-tx-trace.out");
2793 if (!macTxTraceFile.is_open())
2794 {
2795 NS_FATAL_ERROR("Failed to open file wifi-bianchi-mac-tx-trace.out");
2796 }
2797 macRxTraceFile.open("wifi-bianchi-mac-rx-trace.out");
2798 if (!macRxTraceFile.is_open())
2799 {
2800 NS_FATAL_ERROR("Failed to open file wifi-bianchi-mac-rx-trace.out");
2801 }
2802 socketSendTraceFile.open("wifi-bianchi-socket-send-trace.out");
2803 if (!socketSendTraceFile.is_open())
2804 {
2805 NS_FATAL_ERROR("Failed to open file wifi-bianchi-socket-send-trace.out");
2806 }
2807 }
2808
2809 if (verbose >= 1)
2810 {
2811 LogComponentEnable("WifiBianchi", LOG_LEVEL_ALL);
2812 }
2813 else
2814 {
2815 LogComponentEnable("WifiBianchi", LOG_LEVEL_WARN);
2816 }
2817 if (verbose >= 2)
2818 {
2820 }
2821
2822 std::stringstream phyModeStr;
2823 phyModeStr << phyMode;
2824 if (phyMode.find("Mcs") != std::string::npos)
2825 {
2826 phyModeStr << "_" << channelWidth << "MHz";
2827 }
2828
2829 std::stringstream ss;
2830 ss << "wifi-" << standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") << "-r-"
2831 << phyModeStr.str() << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize
2832 << "-throughput.plt";
2833 std::ofstream throughputPlot(ss.str());
2834 ss.str("");
2835 ss << "wifi-" << standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") << "-r-"
2836 << phyModeStr.str() << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize
2837 << "-throughput.eps";
2838 Gnuplot gnuplot = Gnuplot(ss.str());
2839
2840 WifiStandard wifiStandard;
2841 if (standard == "11a")
2842 {
2843 wifiStandard = WIFI_STANDARD_80211a;
2844 frequency = 5;
2845 channelWidth = 20;
2846 }
2847 else if (standard == "11b")
2848 {
2849 wifiStandard = WIFI_STANDARD_80211b;
2850 frequency = 2.4;
2851 channelWidth = 22;
2852 }
2853 else if (standard == "11g")
2854 {
2855 wifiStandard = WIFI_STANDARD_80211g;
2856 frequency = 2.4;
2857 channelWidth = 20;
2858 }
2859 else if (standard == "11n")
2860 {
2861 if (frequency == 2.4 || frequency == 5)
2862 {
2863 wifiStandard = WIFI_STANDARD_80211n;
2864 }
2865 else
2866 {
2867 NS_FATAL_ERROR("Unsupported frequency band " << frequency << " GHz for standard "
2868 << standard);
2869 }
2870 }
2871 else if (standard == "11ac")
2872 {
2873 wifiStandard = WIFI_STANDARD_80211ac;
2874 frequency = 5;
2875 }
2876 else if (standard == "11ax")
2877 {
2878 if (frequency == 2.4 || frequency == 5 || frequency == 6)
2879 {
2880 wifiStandard = WIFI_STANDARD_80211ax;
2881 }
2882 else
2883 {
2884 NS_FATAL_ERROR("Unsupported frequency band " << frequency << " GHz for standard "
2885 << standard);
2886 }
2887 }
2888 else
2889 {
2890 NS_FATAL_ERROR("Unsupported standard: " << standard);
2891 }
2892
2893 std::string channelStr = "{0, " + std::to_string(channelWidth) + ", BAND_" +
2894 (frequency == 2.4 ? "2_4" : (frequency == 5 ? "5" : "6")) + "GHZ, 0}";
2895 Config::SetDefault("ns3::WifiPhy::ChannelSettings", StringValue(channelStr));
2896
2897 YansWifiPhyHelper wifiPhy;
2899
2900 YansWifiChannelHelper wifiChannel;
2901 wifiChannel.SetPropagationDelay("ns3::ConstantSpeedPropagationDelayModel");
2902 if (frequency == 6)
2903 {
2904 // Reference Loss for Friss at 1 m with 6.0 GHz
2905 wifiChannel.AddPropagationLoss("ns3::LogDistancePropagationLossModel",
2906 "Exponent",
2907 DoubleValue(2.0),
2908 "ReferenceDistance",
2909 DoubleValue(1.0),
2910 "ReferenceLoss",
2911 DoubleValue(49.013));
2912 }
2913 else if (frequency == 5)
2914 {
2915 // Reference Loss for Friss at 1 m with 5.15 GHz
2916 wifiChannel.AddPropagationLoss("ns3::LogDistancePropagationLossModel",
2917 "Exponent",
2918 DoubleValue(2.0),
2919 "ReferenceDistance",
2920 DoubleValue(1.0),
2921 "ReferenceLoss",
2922 DoubleValue(46.6777));
2923 }
2924 else
2925 {
2926 // Reference Loss for Friss at 1 m with 2.4 GHz
2927 wifiChannel.AddPropagationLoss("ns3::LogDistancePropagationLossModel",
2928 "Exponent",
2929 DoubleValue(2.0),
2930 "ReferenceDistance",
2931 DoubleValue(1.0),
2932 "ReferenceLoss",
2933 DoubleValue(40.046));
2934 }
2935
2937 wifi.SetStandard(wifiStandard);
2938 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
2939 "DataMode",
2940 StringValue(phyMode),
2941 "ControlMode",
2942 StringValue(phyMode));
2943
2944 Gnuplot2dDataset dataset;
2945 Gnuplot2dDataset datasetBianchiEifs;
2946 Gnuplot2dDataset datasetBianchiDifs;
2949 datasetBianchiEifs.SetStyle(Gnuplot2dDataset::LINES_POINTS);
2950 datasetBianchiDifs.SetStyle(Gnuplot2dDataset::LINES_POINTS);
2951
2953 WifiMacHelper wifiMac;
2954 double averageThroughput;
2955 std::vector<double> throughputArray(trials);
2956 for (uint32_t n = nMinStas; n <= nMaxStas; n += nStepSize)
2957 {
2958 averageThroughput = 0;
2959 double throughput;
2960 for (uint32_t runIndex = 0; runIndex < trials; runIndex++)
2961 {
2962 packetsReceived.clear();
2963 bytesReceived.clear();
2964 packetsTransmitted.clear();
2965 psduFailed.clear();
2966 psduSucceeded.clear();
2967 phyHeaderFailed.clear();
2968 timeFirstReceived.clear();
2969 timeLastReceived.clear();
2971 rxEventWhileRxing.clear();
2972 rxEventWhileTxing.clear();
2973 rxEventAbortedByTx.clear();
2974 associated.clear();
2975 throughput = 0;
2976 std::cout << "Trial " << runIndex + 1 << " of " << trials << "; " << phyModeStr.str()
2977 << " for " << n << " nodes " << std::endl;
2978 if (tracing)
2979 {
2980 cwTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
2981 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
2982 backoffTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
2983 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
2984 phyTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
2985 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
2986 macTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
2987 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
2988 macRxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
2989 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
2990 socketSendTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "
2991 << phyModeStr.str() << " for " << n << " nodes" << std::endl;
2992 }
2993 experiment.Run(wifi,
2994 wifiPhy,
2995 wifiMac,
2996 wifiChannel,
2997 runIndex,
2998 n,
2999 Seconds(duration),
3000 pcap,
3001 infra,
3002 guardIntervalNs,
3003 distance,
3004 apTxPower,
3005 staTxPower,
3006 MicroSeconds(pktInterval));
3007 uint32_t k = 0;
3008 if (bytesReceived.size() != n)
3009 {
3010 NS_FATAL_ERROR("Not all stations got traffic!");
3011 }
3012 for (auto it = bytesReceived.begin(); it != bytesReceived.end(); it++, k++)
3013 {
3014 Time first = timeFirstReceived.find(it->first)->second;
3015 Time last = timeLastReceived.find(it->first)->second;
3016 Time dataTransferDuration = last - first;
3017 double nodeThroughput =
3018 (it->second * 8 / static_cast<double>(dataTransferDuration.GetMicroSeconds()));
3019 throughput += nodeThroughput;
3020 uint64_t nodeTxPackets = GetCount(packetsTransmitted, it->first);
3021 uint64_t nodeRxPackets = GetCount(packetsReceived, it->first);
3022 uint64_t nodePhyHeaderFailures = GetCount(phyHeaderFailed, it->first);
3023 uint64_t nodePsduFailures = GetCount(psduFailed, it->first);
3024 uint64_t nodePsduSuccess = GetCount(psduSucceeded, it->first);
3025 uint64_t nodeRxEventWhileDecodingPreamble =
3027 uint64_t nodeRxEventWhileRxing = GetCount(rxEventWhileRxing, it->first);
3028 uint64_t nodeRxEventWhileTxing = GetCount(rxEventWhileTxing, it->first);
3029 uint64_t nodeRxEventAbortedByTx = GetCount(rxEventAbortedByTx, it->first);
3030 uint64_t nodeRxEvents = nodePhyHeaderFailures + nodePsduFailures + nodePsduSuccess +
3031 nodeRxEventWhileDecodingPreamble + nodeRxEventWhileRxing +
3032 nodeRxEventWhileTxing + nodeRxEventAbortedByTx;
3033 std::cout << "Node " << it->first << ": TX packets " << nodeTxPackets
3034 << "; RX packets " << nodeRxPackets << "; PHY header failures "
3035 << nodePhyHeaderFailures << "; PSDU failures " << nodePsduFailures
3036 << "; PSDU success " << nodePsduSuccess
3037 << "; RX events while decoding preamble "
3038 << nodeRxEventWhileDecodingPreamble << "; RX events while RXing "
3039 << nodeRxEventWhileRxing << "; RX events while TXing "
3040 << nodeRxEventWhileTxing << "; RX events aborted by TX "
3041 << nodeRxEventAbortedByTx << "; total RX events " << nodeRxEvents
3042 << "; total events " << nodeTxPackets + nodeRxEvents << "; time first RX "
3043 << first << "; time last RX " << last << "; dataTransferDuration "
3044 << dataTransferDuration << "; throughput " << nodeThroughput << " Mbps"
3045 << std::endl;
3046 }
3047 std::cout << "Total throughput: " << throughput << " Mbps" << std::endl;
3048 averageThroughput += throughput;
3049 throughputArray[runIndex] = throughput;
3050 }
3051 averageThroughput = averageThroughput / trials;
3052
3053 bool rateFound = false;
3054 double relativeErrorDifs = 0;
3055 double relativeErrorEifs = 0;
3056 auto itDifs = bianchiResultsDifs.find(phyModeStr.str());
3057 if (itDifs != bianchiResultsDifs.end())
3058 {
3059 rateFound = true;
3060 auto it = itDifs->second.find(n);
3061 if (it != itDifs->second.end())
3062 {
3063 relativeErrorDifs = (std::abs(averageThroughput - it->second) / it->second);
3064 std::cout << "Relative error (DIFS): " << 100 * relativeErrorDifs << "%"
3065 << std::endl;
3066 }
3067 else if (validate)
3068 {
3069 NS_FATAL_ERROR("No Bianchi results (DIFS) calculated for that number of stations!");
3070 }
3071 }
3072 auto itEifs = bianchiResultsEifs.find(phyModeStr.str());
3073 if (itEifs != bianchiResultsEifs.end())
3074 {
3075 rateFound = true;
3076 auto it = itEifs->second.find(n);
3077 if (it != itEifs->second.end())
3078 {
3079 relativeErrorEifs = (std::abs(averageThroughput - it->second) / it->second);
3080 std::cout << "Relative error (EIFS): " << 100 * relativeErrorEifs << "%"
3081 << std::endl;
3082 }
3083 else if (validate)
3084 {
3085 NS_FATAL_ERROR("No Bianchi results (EIFS) calculated for that number of stations!");
3086 }
3087 }
3088 if (!rateFound && validate)
3089 {
3090 NS_FATAL_ERROR("No Bianchi results calculated for that rate!");
3091 }
3092 double relativeError = std::min(relativeErrorDifs, relativeErrorEifs);
3093 if (validate && (relativeError > maxRelativeError))
3094 {
3095 NS_FATAL_ERROR("Relative error is too high!");
3096 }
3097
3098 double stDev = 0;
3099 for (uint32_t i = 0; i < trials; ++i)
3100 {
3101 stDev += pow(throughputArray[i] - averageThroughput, 2);
3102 }
3103 stDev = sqrt(stDev / (trials - 1));
3104 dataset.Add(n, averageThroughput, stDev);
3105 }
3106 dataset.SetTitle("ns-3");
3107
3108 auto itDifs = bianchiResultsDifs.find(phyModeStr.str());
3109 if (itDifs != bianchiResultsDifs.end())
3110 {
3111 for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3112 {
3113 double value = 0.0;
3114 auto it = itDifs->second.find(i);
3115 if (it != itDifs->second.end())
3116 {
3117 value = it->second;
3118 }
3119 datasetBianchiDifs.Add(i, value);
3120 }
3121 }
3122 else
3123 {
3124 for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3125 {
3126 datasetBianchiDifs.Add(i, 0.0);
3127 }
3128 }
3129
3130 auto itEifs = bianchiResultsEifs.find(phyModeStr.str());
3131 if (itEifs != bianchiResultsEifs.end())
3132 {
3133 for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3134 {
3135 double value = 0.0;
3136 auto it = itEifs->second.find(i);
3137 if (it != itEifs->second.end())
3138 {
3139 value = it->second;
3140 }
3141 datasetBianchiEifs.Add(i, value);
3142 }
3143 }
3144 else
3145 {
3146 for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3147 {
3148 datasetBianchiEifs.Add(i, 0.0);
3149 }
3150 }
3151
3152 datasetBianchiEifs.SetTitle("Bianchi (EIFS - lower bound)");
3153 datasetBianchiDifs.SetTitle("Bianchi (DIFS - upper bound)");
3154 gnuplot.AddDataset(dataset);
3155 gnuplot.SetTerminal("postscript eps color enh \"Times-BoldItalic\"");
3156 gnuplot.SetLegend("Number of competing stations", "Throughput (Mbps)");
3157 ss.str("");
3158 ss << "Frame size " << pktSize << " bytes";
3159 gnuplot.SetTitle(ss.str());
3160 ss.str("");
3161 ss << "set xrange [" << nMinStas << ":" << nMaxStas << "]\n"
3162 << "set xtics " << nStepSize << "\n"
3163 << "set grid xtics ytics\n"
3164 << "set mytics\n"
3165 << "set style line 1 linewidth 5\n"
3166 << "set style line 2 linewidth 5\n"
3167 << "set style line 3 linewidth 5\n"
3168 << "set style line 4 linewidth 5\n"
3169 << "set style line 5 linewidth 5\n"
3170 << "set style line 6 linewidth 5\n"
3171 << "set style line 7 linewidth 5\n"
3172 << "set style line 8 linewidth 5\n"
3173 << "set style increment user";
3174 gnuplot.SetExtra(ss.str());
3175 if (plotBianchiModel & 0x0001)
3176 {
3177 datasetBianchiDifs.SetTitle("Bianchi");
3178 gnuplot.AddDataset(datasetBianchiDifs);
3179 }
3180 if (plotBianchiModel & 0x0002)
3181 {
3182 datasetBianchiEifs.SetTitle("Bianchi");
3183 gnuplot.AddDataset(datasetBianchiEifs);
3184 }
3185 if (plotBianchiModel == 0x0003)
3186 {
3187 datasetBianchiEifs.SetTitle("Bianchi (EIFS - lower bound)");
3188 datasetBianchiDifs.SetTitle("Bianchi (DIFS - upper bound)");
3189 }
3190 gnuplot.GenerateOutput(throughputPlot);
3191 throughputPlot.close();
3192
3193 if (tracing)
3194 {
3195 cwTraceFile.close();
3196 backoffTraceFile.close();
3197 phyTxTraceFile.close();
3198 macTxTraceFile.close();
3199 macRxTraceFile.close();
3200 socketSendTraceFile.close();
3201 }
3202
3203 return 0;
3204}
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:1395
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:1332
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
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.