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