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