A Discrete-Event Network Simulator
API
wifi-bianchi.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 The Boeing Company
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Gary Pei <guangyu.pei@boeing.com>
19  *
20  * Updated by Tom Henderson, Rohan Patidar, Hao Yin and S├ębastien Deronne
21  */
22 
23 // This program conducts a Bianchi analysis of a wifi network.
24 // It currently only supports 11a/b/g, and will be later extended
25 // to support 11n/ac/ax, including frame aggregation settings.
26 
27 #include <fstream>
28 #include "ns3/log.h"
29 #include "ns3/config.h"
30 #include "ns3/gnuplot.h"
31 #include "ns3/string.h"
32 #include "ns3/double.h"
33 #include "ns3/integer.h"
34 #include "ns3/uinteger.h"
35 #include "ns3/command-line.h"
36 #include "ns3/node-list.h"
37 #include "ns3/yans-wifi-helper.h"
38 #include "ns3/ssid.h"
39 #include "ns3/wifi-mac-header.h"
40 #include "ns3/queue-size.h"
41 #include "ns3/propagation-loss-model.h"
42 #include "ns3/propagation-delay-model.h"
43 #include "ns3/rng-seed-manager.h"
44 #include "ns3/mobility-helper.h"
45 #include "ns3/wifi-net-device.h"
46 #include "ns3/packet-socket-helper.h"
47 #include "ns3/packet-socket-client.h"
48 #include "ns3/packet-socket-server.h"
49 #include "ns3/application-container.h"
50 
51 #define PI 3.1415926535
52 
53 NS_LOG_COMPONENT_DEFINE ("WifiBianchi");
54 
55 using namespace ns3;
56 
57 std::ofstream cwTraceFile;
58 std::ofstream backoffTraceFile;
59 std::ofstream phyTxTraceFile;
60 std::ofstream macTxTraceFile;
61 std::ofstream macRxTraceFile;
62 std::ofstream socketSendTraceFile;
63 
64 std::map<Mac48Address, uint64_t> packetsReceived;
65 std::map<Mac48Address, uint64_t> bytesReceived;
66 std::map<Mac48Address, uint64_t> packetsTransmitted;
67 std::map<Mac48Address, uint64_t> psduFailed;
68 std::map<Mac48Address, uint64_t> psduSucceeded;
69 std::map<Mac48Address, uint64_t> phyHeaderFailed;
70 std::map<Mac48Address, uint64_t> rxEventWhileTxing;
71 std::map<Mac48Address, uint64_t> rxEventWhileRxing;
72 std::map<Mac48Address, uint64_t> rxEventWhileDecodingPreamble;
73 std::map<Mac48Address, uint64_t> rxEventAbortedByTx;
74 
75 std::map<Mac48Address, Time> timeFirstReceived;
76 std::map<Mac48Address, Time> timeLastReceived;
77 std::map<Mac48Address, Time> timeFirstTransmitted;
78 std::map<Mac48Address, Time> timeLastTransmitted;
79 
80 std::set<uint32_t> associated;
81 
82 bool tracing = false;
83 uint32_t pktSize = 1500;
84 
85 std::map<unsigned int /* rate (bit/s)*/, std::map<unsigned int /* number of nodes */, double /* calculated throughput */> > bianchiResultsEifs =
86 {
87 /* 11b */
88  {1000000, {
89  {5, 0.8418},
90  {10, 0.7831},
91  {15, 0.7460},
92  {20, 0.7186},
93  {25, 0.6973},
94  {30, 0.6802},
95  {35, 0.6639},
96  {40, 0.6501},
97  {45, 0.6386},
98  {50, 0.6285},
99  }},
100  {2000000, {
101  {5, 1.6170},
102  {10, 1.5075},
103  {15, 1.4371},
104  {20, 1.3849},
105  {25, 1.3442},
106  {30, 1.3115},
107  {35, 1.2803},
108  {40, 1.2538},
109  {45, 1.2317},
110  {50, 1.2124},
111  }},
112  {5500000, {
113  {5, 3.8565},
114  {10, 3.6170},
115  {15, 3.4554},
116  {20, 3.3339},
117  {25, 3.2385},
118  {30, 3.1613},
119  {35, 3.0878},
120  {40, 3.0249},
121  {45, 2.9725},
122  {50, 2.9266},
123  }},
124  {11000000, {
125  {5, 6.3821},
126  {10, 6.0269},
127  {15, 5.7718},
128  {20, 5.5765},
129  {25, 5.4217},
130  {30, 5.2958},
131  {35, 5.1755},
132  {40, 5.0722},
133  {45, 4.9860},
134  {50, 4.9103},
135  }},
136 /* 11a/g */
137  {6000000, {
138  {5, 4.6899},
139  {10, 4.3197},
140  {15, 4.1107},
141  {20, 3.9589},
142  {25, 3.8478},
143  {30, 3.7490},
144  {35, 3.6618},
145  {40, 3.5927},
146  {45, 3.5358},
147  {50, 3.4711},
148  }},
149  {9000000, {
150  {5, 6.8188},
151  {10, 6.2885},
152  {15, 5.9874},
153  {20, 5.7680},
154  {25, 5.6073},
155  {30, 5.4642},
156  {35, 5.3378},
157  {40, 5.2376},
158  {45, 5.1551},
159  {50, 5.0612},
160  }},
161  {12000000, {
162  {5, 8.8972},
163  {10, 8.2154},
164  {15, 7.8259},
165  {20, 7.5415},
166  {25, 7.3329},
167  {30, 7.1469},
168  {35, 6.9825},
169  {40, 6.8521},
170  {45, 6.7447},
171  {50, 6.6225},
172  }},
173  {18000000, {
174  {5, 12.6719},
175  {10, 11.7273},
176  {15, 11.1814},
177  {20, 10.7810},
178  {25, 10.4866},
179  {30, 10.2237},
180  {35, 9.9910},
181  {40, 9.8061},
182  {45, 9.6538},
183  {50, 9.4804},
184  }},
185  {24000000, {
186  {5, 16.0836},
187  {10, 14.9153},
188  {15, 14.2327},
189  {20, 13.7300},
190  {25, 13.3595},
191  {30, 13.0281},
192  {35, 12.7343},
193  {40, 12.5008},
194  {45, 12.3083},
195  {50, 12.0889},
196  }},
197  {36000000, {
198  {5, 22.0092},
199  {10, 20.4836},
200  {15, 19.5743},
201  {20, 18.8997},
202  {25, 18.4002},
203  {30, 17.9524},
204  {35, 17.5545},
205  {40, 17.2377},
206  {45, 16.9760},
207  {50, 16.6777},
208  }},
209  {48000000, {
210  {5, 26.8382},
211  {10, 25.0509},
212  {15, 23.9672},
213  {20, 23.1581},
214  {25, 22.5568},
215  {30, 22.0165},
216  {35, 21.5355},
217  {40, 21.1519},
218  {45, 20.8348},
219  {50, 20.4729},
220  }},
221  {54000000, {
222  {5, 29.2861},
223  {10, 27.3763},
224  {15, 26.2078},
225  {20, 25.3325},
226  {25, 24.6808},
227  {30, 24.0944},
228  {35, 23.5719},
229  {40, 23.1549},
230  {45, 22.8100},
231  {50, 22.4162},
232  }},
233 };
234 
235 std::map<unsigned int /* rate (bit/s)*/, std::map<unsigned int /* number of nodes */, double /* calculated throughput */> > bianchiResultsDifs =
236 {
237 /* 11b */
238  {1000000, {
239  {5, 0.8437},
240  {10, 0.7861},
241  {15, 0.7496},
242  {20, 0.7226},
243  {25, 0.7016},
244  {30, 0.6847},
245  {35, 0.6686},
246  {40, 0.6549},
247  {45, 0.6435},
248  {50, 0.6336},
249  }},
250  {2000000, {
251  {5, 1.6228},
252  {10, 1.5168},
253  {15, 1.4482},
254  {20, 1.3972},
255  {25, 1.3574},
256  {30, 1.3253},
257  {35, 1.2947},
258  {40, 1.2687},
259  {45, 1.2469},
260  {50, 1.2279},
261  }},
262  {5500000, {
263  {5, 3.8896},
264  {10, 3.6707},
265  {15, 3.5203},
266  {20, 3.4063},
267  {25, 3.3161},
268  {30, 3.2429},
269  {35, 3.1729},
270  {40, 3.1128},
271  {45, 3.0625},
272  {50, 3.0184},
273  }},
274  {11000000, {
275  {5, 6.4734},
276  {10, 6.1774},
277  {15, 5.9553},
278  {20, 5.7819},
279  {25, 5.6429},
280  {30, 5.5289},
281  {35, 5.4191},
282  {40, 5.3243},
283  {45, 5.2446},
284  {50, 5.1745},
285  }},
286 /* 11a/g */
287  {6000000, {
288  {5, 4.7087},
289  {10, 4.3453},
290  {15, 4.1397},
291  {20, 3.9899},
292  {25, 3.8802},
293  {30, 3.7824},
294  {35, 3.6961},
295  {40, 3.6276},
296  {45, 3.5712},
297  {50, 3.5071},
298  }},
299  {9000000, {
300  {5, 6.8586},
301  {10, 6.3431},
302  {15, 6.0489},
303  {20, 5.8340},
304  {25, 5.6762},
305  {30, 5.5355},
306  {35, 5.4110},
307  {40, 5.3122},
308  {45, 5.2307},
309  {50, 5.1380},
310  }},
311  {12000000, {
312  {5, 8.9515},
313  {10, 8.2901},
314  {15, 7.9102},
315  {20, 7.6319},
316  {25, 7.4274},
317  {30, 7.2447},
318  {35, 7.0829},
319  {40, 6.9544},
320  {45, 6.8485},
321  {50, 6.7278},
322  }},
323  {18000000, {
324  {5, 12.7822},
325  {10, 11.8801},
326  {15, 11.3543},
327  {20, 10.9668},
328  {25, 10.6809},
329  {30, 10.4249},
330  {35, 10.1978},
331  {40, 10.0171},
332  {45, 9.8679},
333  {50, 9.6978},
334  }},
335  {24000000, {
336  {5, 16.2470},
337  {10, 15.1426},
338  {15, 14.4904},
339  {20, 14.0072},
340  {25, 13.6496},
341  {30, 13.3288},
342  {35, 13.0436},
343  {40, 12.8164},
344  {45, 12.6286},
345  {50, 12.4144},
346  }},
347  {36000000, {
348  {5, 22.3164},
349  {10, 20.9147},
350  {15, 20.0649},
351  {20, 19.4289},
352  {25, 18.9552},
353  {30, 18.5284},
354  {35, 18.1476},
355  {40, 17.8434},
356  {45, 17.5915},
357  {50, 17.3036},
358  }},
359  {48000000, {
360  {5, 27.2963},
361  {10, 25.6987},
362  {15, 24.7069},
363  {20, 23.9578},
364  {25, 23.3965},
365  {30, 22.8891},
366  {35, 22.4350},
367  {40, 22.0713},
368  {45, 21.7696},
369  {50, 21.4243},
370  }},
371  {54000000, {
372  {5, 29.8324},
373  {10, 28.1519},
374  {15, 27.0948},
375  {20, 26.2925},
376  {25, 25.6896},
377  {30, 25.1434},
378  {35, 24.6539},
379  {40, 24.2613},
380  {45, 23.9353},
381  {50, 23.5618},
382  }},
383 };
384 
385 // Parse context strings of the form "/NodeList/x/DeviceList/x/..." to extract the NodeId integer
386 uint32_t
387 ContextToNodeId (std::string context)
388 {
389  std::string sub = context.substr (10);
390  uint32_t pos = sub.find ("/Device");
391  return atoi (sub.substr (0, pos).c_str ());
392 }
393 
394 // Parse context strings of the form "/NodeList/x/DeviceList/x/..." and fetch the Mac address
396 ContextToMac (std::string context)
397 {
398  std::string sub = context.substr (10);
399  uint32_t pos = sub.find ("/Device");
400  uint32_t nodeId = atoi (sub.substr (0, pos).c_str ());
401  Ptr<Node> n = NodeList::GetNode (nodeId);
403  for (uint32_t i = 0; i < n->GetNDevices (); i++)
404  {
405  d = n->GetDevice (i)->GetObject<WifiNetDevice> ();
406  if (d)
407  {
408  break;
409  }
410  }
411  return Mac48Address::ConvertFrom (d->GetAddress ());
412 }
413 
414 // Functions for tracing.
415 
416 void
417 IncrementCounter (std::map<Mac48Address, uint64_t> & counter, Mac48Address addr, uint64_t increment = 1)
418 {
419  auto it = counter.find (addr);
420  if (it != counter.end ())
421  {
422  it->second += increment;
423  }
424  else
425  {
426  counter.insert (std::make_pair (addr, increment));
427  }
428 }
429 
430 void
431 TracePacketReception (std::string context, Ptr<const Packet> packet, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise, uint16_t staId)
432 {
433  WifiMacHeader hdr;
434  packet->PeekHeader (hdr);
435  // hdr.GetAddr1() is the receiving MAC address
436  if (hdr.GetAddr1 () != ContextToMac (context))
437  {
438  return;
439  }
440  // hdr.GetAddr2() is the sending MAC address
441  if (packet->GetSize () == (pktSize + 36)) // ignore non-data frames
442  {
445  auto itTimeFirstReceived = timeFirstReceived.find (hdr.GetAddr2 ());
446  if (itTimeFirstReceived == timeFirstReceived.end ())
447  {
448  timeFirstReceived.insert (std::make_pair (hdr.GetAddr2 (), Simulator::Now ()));
449  }
450  auto itTimeLastReceived = timeLastReceived.find (hdr.GetAddr2 ());
451  if (itTimeLastReceived != timeLastReceived.end ())
452  {
453  itTimeLastReceived->second = Simulator::Now ();
454  }
455  else
456  {
457  timeLastReceived.insert (std::make_pair (hdr.GetAddr2 (), Simulator::Now ()));
458  }
459  }
460 }
461 
462 void
463 CwTrace (std::string context, uint32_t oldVal, uint32_t newVal)
464 {
465  NS_LOG_INFO ("CW time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " val=" << newVal);
466  if (tracing)
467  {
468  cwTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << newVal << std::endl;
469  }
470 }
471 
472 void
473 BackoffTrace (std::string context, uint32_t newVal)
474 {
475  NS_LOG_INFO ("Backoff time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " val=" << newVal);
476  if (tracing)
477  {
478  backoffTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << newVal << std::endl;
479  }
480 }
481 
482 void
484 {
485  NS_LOG_INFO ("PHY-RX-START time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize ());
486 }
487 
488 void
489 PhyRxPayloadTrace (std::string context, WifiTxVector txVector, Time psduDuration)
490 {
491  NS_LOG_INFO ("PHY-RX-PAYLOAD-START time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " psduDuration=" << psduDuration);
492 }
493 
494 void
496 {
497  NS_LOG_INFO ("PHY-RX-DROP time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize () << " reason=" << reason);
498  Mac48Address addr = ContextToMac (context);
499  switch (reason)
500  {
502  NS_FATAL_ERROR ("RX packet with unsupported settings!");
503  break;
504  case CHANNEL_SWITCHING:
505  NS_FATAL_ERROR ("Channel is switching!");
506  break;
508  {
509  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
510  {
512  }
513  break;
514  }
515  case RXING:
516  {
517  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
518  {
520  }
521  break;
522  }
523  case TXING:
524  {
525  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
526  {
528  }
529  break;
530  }
531  case SLEEPING:
532  NS_FATAL_ERROR ("Device is sleeping!");
533  break;
535  NS_FATAL_ERROR ("Preamble should always be detected!");
536  break;
538  {
539  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
540  {
542  }
543  break;
544  }
545  case L_SIG_FAILURE:
546  {
547  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
548  {
550  }
551  break;
552  }
553  case HT_SIG_FAILURE:
554  case SIG_A_FAILURE:
555  case SIG_B_FAILURE:
556  NS_FATAL_ERROR ("Unexpected PHY header failure!");
558  NS_FATAL_ERROR ("All devices should send with same power, so no packet switch during preamble detection should occur!");
559  break;
561  NS_FATAL_ERROR ("Frame capture should be disabled!");
562  break;
563  case OBSS_PD_CCA_RESET:
564  NS_FATAL_ERROR ("Unexpected CCA reset!");
565  break;
566  case UNKNOWN:
567  default:
568  NS_FATAL_ERROR ("Unknown drop reason!");
569  break;
570  }
571 }
572 
573 void
574 PhyRxDoneTrace (std::string context, Ptr<const Packet> p)
575 {
576  NS_LOG_INFO ("PHY-RX-END time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize ());
577 }
578 
579 void
580 PhyRxOkTrace (std::string context, Ptr<const Packet> p, double snr, WifiMode mode, WifiPreamble preamble)
581 {
582  NS_LOG_INFO ("PHY-RX-OK time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize () << " snr=" << snr << " mode=" << mode << " preamble=" << preamble);
583  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
584  {
585  Mac48Address addr = ContextToMac (context);
587  }
588 }
589 
590 void
591 PhyRxErrorTrace (std::string context, Ptr<const Packet> p, double snr)
592 {
593  NS_LOG_INFO ("PHY-RX-ERROR time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize () << " snr=" << snr);
594  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
595  {
596  Mac48Address addr = ContextToMac (context);
598  }
599 }
600 
601 void
602 PhyTxTrace (std::string context, Ptr<const Packet> p, double txPowerW)
603 {
604  NS_LOG_INFO ("PHY-TX-START time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize () << " " << txPowerW);
605  if (tracing)
606  {
607  phyTxTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " size=" << p->GetSize () << " " << txPowerW << std::endl;
608  }
609  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
610  {
611  Mac48Address addr = ContextToMac (context);
613  }
614 }
615 
616 void
617 PhyTxDoneTrace (std::string context, Ptr<const Packet> p)
618 {
619  NS_LOG_INFO ("PHY-TX-END time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " " << p->GetSize ());
620 }
621 
622 void
623 MacTxTrace (std::string context, Ptr<const Packet> p)
624 {
625  if (tracing)
626  {
627  macTxTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << p->GetSize () << std::endl;
628  }
629 }
630 
631 void
632 MacRxTrace (std::string context, Ptr<const Packet> p)
633 {
634  if (tracing)
635  {
636  macRxTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << p->GetSize () << std::endl;
637  }
638 }
639 
640 void
641 SocketSendTrace (std::string context, Ptr<const Packet> p, const Address &addr)
642 {
643  if (tracing)
644  {
645  socketSendTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << p->GetSize () << " " << addr << std::endl;
646  }
647 }
648 
649 void
650 AssociationLog (std::string context, Mac48Address address)
651 {
652  uint32_t nodeId = ContextToNodeId (context);
653  auto it = associated.find (nodeId);
654  if (it == associated.end ())
655  {
656  NS_LOG_DEBUG ("Association: time=" << Simulator::Now () << " node=" << nodeId);
657  associated.insert (it, nodeId);
658  }
659  else
660  {
661  NS_FATAL_ERROR (nodeId << " is already associated!");
662  }
663 }
664 
665 void
666 DisassociationLog (std::string context, Mac48Address address)
667 {
668  uint32_t nodeId = ContextToNodeId (context);
669  NS_LOG_DEBUG ("Disassociation: time=" << Simulator::Now () << " node=" << nodeId);
670  NS_FATAL_ERROR ("Device should not disassociate!");
671 }
672 
673 void
675 {
676  bytesReceived.clear ();
677  packetsReceived.clear ();
678  packetsTransmitted.clear ();
679  psduFailed.clear ();
680  psduSucceeded.clear ();
681  phyHeaderFailed.clear ();
682  timeFirstReceived.clear ();
683  timeLastReceived.clear ();
685  rxEventWhileRxing.clear ();
686  rxEventWhileTxing.clear ();
687  rxEventAbortedByTx.clear ();
688 }
689 
690 class Experiment
691 {
692 public:
693  Experiment ();
694  int Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel,
695  uint32_t trialNumber, uint32_t networkSize, double duration, bool pcap, bool infra);
696 };
697 
699 {
700 }
701 
702 int
703 Experiment::Run (const WifiHelper &helper, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel,
704  uint32_t trialNumber, uint32_t networkSize, double duration, bool pcap, bool infra)
705 {
706  NodeContainer wifiNodes;
707  if (infra)
708  {
709  wifiNodes.Create (networkSize + 1);
710  }
711  else
712  {
713  wifiNodes.Create (networkSize);
714  }
715 
716  YansWifiPhyHelper phy = wifiPhy;
717  phy.SetErrorRateModel ("ns3::NistErrorRateModel");
718  phy.SetChannel (wifiChannel.Create ());
719  phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
720 
721  WifiMacHelper mac = wifiMac;
722  WifiHelper wifi = helper;
724  uint32_t nNodes = wifiNodes.GetN ();
725  if (infra)
726  {
727  Ssid ssid = Ssid ("wifi-bianchi");
728  uint64_t beaconInterval = std::min<uint64_t> ((ceil ((duration * 1000000) / 1024) * 1024), (65535 * 1024)); //beacon interval needs to be a multiple of time units (1024 us)
729  mac.SetType ("ns3::ApWifiMac",
730  "BeaconInterval", TimeValue (MicroSeconds (beaconInterval)),
731  "Ssid", SsidValue (ssid));
732  devices = wifi.Install (phy, mac, wifiNodes.Get (0));
733 
734  mac.SetType ("ns3::StaWifiMac",
735  "MaxMissedBeacons", UintegerValue (std::numeric_limits<uint32_t>::max ()),
736  "Ssid", SsidValue (ssid));
737  for (uint32_t i = 1; i < nNodes; ++i)
738  {
739  devices.Add (wifi.Install (phy, mac, wifiNodes.Get (i)));
740  }
741  }
742  else
743  {
744  mac.SetType ("ns3::AdhocWifiMac");
745  devices = wifi.Install (phy, mac, wifiNodes);
746  }
747 
748  wifi.AssignStreams (devices, trialNumber);
749 
751  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
752  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
753  // Set postion for AP
754  positionAlloc->Add (Vector (1.0, 1.0, 0.0));
755 
756  // Set postion for STAs
757  double angle = (static_cast<double> (360) / (nNodes - 1));
758  for (uint32_t i = 0; i < (nNodes - 1); ++i)
759  {
760  positionAlloc->Add (Vector (1.0 + (0.001 * cos ((i * angle * PI) / 180)), 1.0 + (0.001 * sin ((i * angle * PI) / 180)), 0.0));
761  }
762 
763  mobility.SetPositionAllocator (positionAlloc);
764  mobility.Install (wifiNodes);
765 
766  PacketSocketHelper packetSocket;
767  packetSocket.Install (wifiNodes);
768 
770  Ptr<UniformRandomVariable> startTime = CreateObject<UniformRandomVariable> ();
771  startTime->SetAttribute ("Stream", IntegerValue (trialNumber));
772  startTime->SetAttribute ("Max", DoubleValue (5.0));
773 
774  uint32_t i = infra ? 1 : 0;
775  for (; i < nNodes; ++i)
776  {
777  uint32_t j = infra ? 0 : (i + 1) % nNodes;
778  PacketSocketAddress socketAddr;
779  socketAddr.SetSingleDevice (devices.Get (i)->GetIfIndex ());
780  socketAddr.SetPhysicalAddress (devices.Get (j)->GetAddress ());
781  socketAddr.SetProtocol (1);
782 
783  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient> ();
784  client->SetRemote (socketAddr);
785  wifiNodes.Get (i)->AddApplication (client);
786  client->SetAttribute ("PacketSize", UintegerValue (pktSize));
787  client->SetAttribute ("MaxPackets", UintegerValue (0));
788  client->SetAttribute ("Interval", TimeValue (MilliSeconds (1))); //TODO: reduce it for lower rates, increase it for higher rates
789  double start = startTime->GetValue ();
790  NS_LOG_DEBUG ("Client " << i << " starting at " << start);
791  client->SetStartTime (Seconds (start));
792 
793  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
794  server->SetLocal (socketAddr);
795  wifiNodes.Get (j)->AddApplication (server);
796  }
797 
798  // Log packet receptions
799  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/MonitorSnifferRx", MakeCallback (&TracePacketReception));
800 
801  // Log association and disassociation
802  if (infra)
803  {
804  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/Assoc", MakeCallback (&AssociationLog));
805  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/DeAssoc", MakeCallback (&DisassociationLog));
806  }
807 
808  // Trace CW evolution
809  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::RegularWifiMac/Txop/CwTrace", MakeCallback (&CwTrace));
810  // Trace backoff evolution
811  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::RegularWifiMac/Txop/BackoffTrace", MakeCallback (&BackoffTrace));
812  // Trace PHY Tx start events
813  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxBegin", MakeCallback (&PhyTxTrace));
814  // Trace PHY Tx end events
815  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxEnd", MakeCallback (&PhyTxDoneTrace));
816  // Trace PHY Rx start events
817  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxBegin", MakeCallback (&PhyRxTrace));
818  // Trace PHY Rx payload start events
819  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxPayloadBegin", MakeCallback (&PhyRxPayloadTrace));
820  // Trace PHY Rx drop events
821  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxDrop", MakeCallback (&PhyRxDropTrace));
822  // Trace PHY Rx end events
823  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxEnd", MakeCallback (&PhyRxDoneTrace));
824  // Trace PHY Rx error events
825  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxError", MakeCallback (&PhyRxErrorTrace));
826  // Trace PHY Rx success events
827  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxOk", MakeCallback (&PhyRxOkTrace));
828  // Trace packet transmission by the device
829  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx", MakeCallback (&MacTxTrace));
830  // Trace packet receptions to the device
831  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx", MakeCallback (&MacRxTrace));
832  // Trace packets transmitted by the application
833  Config::Connect ("/NodeList/*/$ns3::Node/ApplicationList/*/$ns3::PacketSocketClient/Tx", MakeCallback (&SocketSendTrace));
834 
836  Simulator::Stop (Seconds (10 + duration));
837 
838  if (pcap)
839  {
840  phy.EnablePcap ("wifi_bianchi_pcap", devices);
841  }
842 
843  Simulator::Run ();
845 
846  if (tracing)
847  {
848  cwTraceFile.flush ();
849  backoffTraceFile.flush ();
850  phyTxTraceFile.flush ();
851  macTxTraceFile.flush ();
852  macRxTraceFile.flush ();
853  socketSendTraceFile.flush ();
854  }
855 
856  return 0;
857 }
858 
859 uint64_t
860 GetCount (const std::map<Mac48Address, uint64_t> & counter, Mac48Address addr)
861 {
862  uint64_t count = 0;
863  auto it = counter.find (addr);
864  if (it != counter.end ())
865  {
866  count = it->second;
867  }
868  return count;
869 }
870 
871 int main (int argc, char *argv[])
872 {
873  uint32_t nMinStas = 5;
874  uint32_t nMaxStas = 50;
875  uint32_t nStepSize = 5;
876  uint32_t verbose = 0;
877  double duration = 100;
878  uint32_t trials = 1;
879  bool pcap = false;
880  bool infra = false;
881  std::string workDir = "./";
882  double phyRate = 54;
883  std::string standard ("11a");
884  bool validate = false;
885  uint32_t plotBianchiModel = 0x1;
886  double maxRelativeError = 0.015;
887 
888  // Disable fragmentation and RTS/CTS
889  Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("22000"));
890  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("22000"));
891  // Disable short retransmission failure (make retransmissions persistent)
892  Config::SetDefault ("ns3::WifiRemoteStationManager::MaxSlrc", UintegerValue (std::numeric_limits<uint32_t>::max ()));
893  Config::SetDefault ("ns3::WifiRemoteStationManager::MaxSsrc", UintegerValue (std::numeric_limits<uint32_t>::max ()));
894  // Set maximum queue size to the largest value and set maximum queue delay to be larger than the simulation time
896  Config::SetDefault ("ns3::WifiMacQueue::MaxDelay", TimeValue (Seconds (2 * duration)));
897 
898  CommandLine cmd (__FILE__);
899  cmd.AddValue ("verbose", "Logging level (0: no log - 1: simulation script logs - 2: all logs)", verbose);
900  cmd.AddValue ("tracing", "Generate trace files", tracing);
901  cmd.AddValue ("pktSize", "The packet size in bytes", pktSize);
902  cmd.AddValue ("trials", "The maximal number of runs per network size", trials);
903  cmd.AddValue ("duration", "Time duration for each trial in seconds", duration);
904  cmd.AddValue ("pcap", "Enable/disable PCAP tracing", pcap);
905  cmd.AddValue ("infra", "True to use infrastructure mode, false to use ring adhoc mode", infra);
906  cmd.AddValue ("workDir", "The working directory used to store generated files", workDir);
907  cmd.AddValue ("phyRate", "Set the constant PHY rate in Mbps used to transmit Data frames", phyRate);
908  cmd.AddValue ("standard", "Set the standard (11a, 11b, 11g, 11n, 11ac, 11ax)", standard);
909  cmd.AddValue ("nMinStas", "Minimum number of stations to start with", nMinStas);
910  cmd.AddValue ("nMaxStas", "Maximum number of stations to start with", nMaxStas);
911  cmd.AddValue ("nStepSize", "Number of stations to add at each step", nStepSize);
912  cmd.AddValue ("validate", "Enable/disable validation of the ns-3 simulations against the Bianchi model", validate);
913  cmd.AddValue ("maxRelativeError", "The maximum relative error tolerated between ns-3 results and the Bianchi model (used for regression, i.e. when the validate flag is set)", maxRelativeError);
914  cmd.Parse (argc, argv);
915 
916  if (tracing)
917  {
918  cwTraceFile.open ("wifi-bianchi-cw-trace.out");
919  if (!cwTraceFile.is_open ())
920  {
921  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-cw-trace.out");
922  }
923  backoffTraceFile.open ("wifi-bianchi-backoff-trace.out");
924  if (!backoffTraceFile.is_open ())
925  {
926  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-backoff-trace.out");
927  }
928  phyTxTraceFile.open ("wifi-bianchi-phy-tx-trace.out");
929  if (!phyTxTraceFile.is_open ())
930  {
931  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-phy-tx-trace.out");
932  }
933  macTxTraceFile.open ("wifi-bianchi-mac-tx-trace.out");
934  if (!macTxTraceFile.is_open ())
935  {
936  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-mac-tx-trace.out");
937  }
938  macRxTraceFile.open ("wifi-bianchi-mac-rx-trace.out");
939  if (!macRxTraceFile.is_open ())
940  {
941  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-mac-rx-trace.out");
942  }
943  socketSendTraceFile.open ("wifi-bianchi-socket-send-trace.out");
944  if (!socketSendTraceFile.is_open ())
945  {
946  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-socket-send-trace.out");
947  }
948  }
949 
950  if (verbose >= 1)
951  {
952  LogComponentEnable ("WifiBianchi", LOG_LEVEL_ALL);
953  }
954  if (verbose >= 2)
955  {
957  }
958 
959  std::stringstream ss;
960  ss << "wifi-"<< standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") << "-r-" << phyRate << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize << "-throughput.plt";
961  std::ofstream throughputPlot (ss.str ().c_str ());
962  ss.str ("");
963  ss << "wifi-" << standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") <<"-r-" << phyRate << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize << "-throughput.eps";
964  Gnuplot gnuplot = Gnuplot (ss.str ());
965 
966  WifiStandard wifiStandard;
967  std::stringstream phyRateStr;
968  if (standard == "11a")
969  {
970  wifiStandard = WIFI_STANDARD_80211a;
971  if ((phyRate != 6) && (phyRate != 9) && (phyRate != 12) && (phyRate != 18) && (phyRate != 24) && (phyRate != 36) && (phyRate != 48) && (phyRate != 54))
972  {
973  NS_FATAL_ERROR ("Selected PHY rate " << phyRate << " is not defined in " << standard);
974  }
975  phyRateStr << "OfdmRate" << phyRate << "Mbps";
976  }
977  else if (standard == "11b")
978  {
979  wifiStandard = WIFI_STANDARD_80211b;
980  if ((phyRate != 1) && (phyRate != 2) && (phyRate != 5.5) && (phyRate != 11))
981  {
982  NS_FATAL_ERROR ("Selected PHY rate " << phyRate << " is not defined in " << standard);
983  }
984  if (phyRate == 5.5)
985  {
986  phyRateStr << "DsssRate5_5Mbps";
987  }
988  else
989  {
990  phyRateStr << "DsssRate" << phyRate << "Mbps";
991  }
992  }
993  else if (standard == "11g")
994  {
995  wifiStandard = WIFI_STANDARD_80211g;
996  if ((phyRate != 6) && (phyRate != 9) && (phyRate != 12) && (phyRate != 18) && (phyRate != 24) && (phyRate != 36) && (phyRate != 48) && (phyRate != 54))
997  {
998  NS_FATAL_ERROR ("Selected PHY rate " << phyRate << " is not defined in " << standard);
999  }
1000  phyRateStr << "ErpOfdmRate" << phyRate << "Mbps";
1001  }
1002  else
1003  {
1004  NS_FATAL_ERROR ("Unsupported standard: " << standard);
1005  }
1006 
1007  YansWifiPhyHelper wifiPhy;
1008  YansWifiChannelHelper wifiChannel;
1009  wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
1010  wifiChannel.AddPropagationLoss ("ns3::LogDistancePropagationLossModel");
1011  wifiPhy.DisablePreambleDetectionModel ();
1012 
1013  WifiMacHelper wifiMac;
1014 
1015  WifiHelper wifi;
1016  wifi.SetStandard (wifiStandard);
1017  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue (phyRateStr.str()));
1018 
1019  Gnuplot2dDataset dataset;
1020  Gnuplot2dDataset datasetBianchiEifs;
1021  Gnuplot2dDataset datasetBianchiDifs;
1024  datasetBianchiEifs.SetStyle (Gnuplot2dDataset::LINES_POINTS);
1025  datasetBianchiDifs.SetStyle (Gnuplot2dDataset::LINES_POINTS);
1026 
1028  double averageThroughput, throughputArray[trials];
1029  for (uint32_t n = nMinStas; n <= nMaxStas; n += nStepSize)
1030  {
1031  averageThroughput = 0;
1032  double throughput;
1033  for (uint32_t runIndex = 0; runIndex < trials; runIndex++)
1034  {
1035  packetsReceived.clear ();
1036  bytesReceived.clear ();
1037  packetsTransmitted.clear ();
1038  psduFailed.clear ();
1039  psduSucceeded.clear ();
1040  phyHeaderFailed.clear ();
1041  timeFirstReceived.clear ();
1042  timeLastReceived.clear ();
1044  rxEventWhileRxing.clear ();
1045  rxEventWhileTxing.clear ();
1046  rxEventAbortedByTx.clear ();
1047  associated.clear ();
1048  throughput = 0;
1049  std::cout << "Trial " << runIndex + 1 << " of " << trials << "; "<< phyRate << " Mbps for " << n << " nodes " << std::endl;
1050  if (tracing)
1051  {
1052  cwTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "<< phyRate << " Mbps for " << n << " nodes" << std::endl;
1053  backoffTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "<< phyRate << " Mbps for " << n << " nodes" << std::endl;
1054  phyTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1055  macTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1056  macRxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1057  socketSendTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1058  }
1059  experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, runIndex, n, duration, pcap, infra);
1060  uint32_t k = 0;
1061  if (bytesReceived.size () != n)
1062  {
1063  NS_FATAL_ERROR ("Not all stations got traffic!");
1064  }
1065  for (auto it = bytesReceived.begin (); it != bytesReceived.end (); it++, k++)
1066  {
1067  Time first = timeFirstReceived.find (it->first)->second;
1068  Time last = timeLastReceived.find (it->first)->second;
1069  Time dataTransferDuration = last - first;
1070  double nodeThroughput = (it->second * 8 / static_cast<double> (dataTransferDuration.GetMicroSeconds ()));
1071  throughput += nodeThroughput;
1072  uint64_t nodeTxPackets = GetCount (packetsTransmitted, it->first);
1073  uint64_t nodeRxPackets = GetCount (packetsReceived, it->first);
1074  uint64_t nodePhyHeaderFailures = GetCount (phyHeaderFailed, it->first);
1075  uint64_t nodePsduFailures = GetCount (psduFailed, it->first);
1076  uint64_t nodePsduSuccess = GetCount (psduSucceeded, it->first);
1077  uint64_t nodeRxEventWhileDecodingPreamble = GetCount (rxEventWhileDecodingPreamble, it->first);
1078  uint64_t nodeRxEventWhileRxing = GetCount (rxEventWhileRxing, it->first);
1079  uint64_t nodeRxEventWhileTxing = GetCount (rxEventWhileTxing, it->first);
1080  uint64_t nodeRxEventAbortedByTx = GetCount (rxEventAbortedByTx, it->first);
1081  uint64_t nodeRxEvents =
1082  nodePhyHeaderFailures + nodePsduFailures + nodePsduSuccess + nodeRxEventWhileDecodingPreamble +
1083  nodeRxEventWhileRxing + nodeRxEventWhileTxing + nodeRxEventAbortedByTx;
1084  std::cout << "Node " << it->first
1085  << ": TX packets " << nodeTxPackets
1086  << "; RX packets " << nodeRxPackets
1087  << "; PHY header failures " << nodePhyHeaderFailures
1088  << "; PSDU failures " << nodePsduFailures
1089  << "; PSDU success " << nodePsduSuccess
1090  << "; RX events while decoding preamble " << nodeRxEventWhileDecodingPreamble
1091  << "; RX events while RXing " << nodeRxEventWhileRxing
1092  << "; RX events while TXing " << nodeRxEventWhileTxing
1093  << "; RX events aborted by TX " << nodeRxEventAbortedByTx
1094  << "; total RX events " << nodeRxEvents
1095  << "; total events " << nodeTxPackets + nodeRxEvents
1096  << "; time first RX " << first
1097  << "; time last RX " << last
1098  << "; dataTransferDuration " << dataTransferDuration
1099  << "; throughput " << nodeThroughput << " Mbps" << std::endl;
1100  }
1101  std::cout << "Total throughput: " << throughput << " Mbps" << std::endl;
1102  averageThroughput += throughput;
1103  throughputArray[runIndex] = throughput;
1104  }
1105  averageThroughput = averageThroughput / trials;
1106 
1107  bool rateFound = false;
1108  double relativeErrorDifs = 0;
1109  double relativeErrorEifs = 0;
1110  auto itDifs = bianchiResultsDifs.find (static_cast<unsigned int> (phyRate * 1000000));
1111  if (itDifs != bianchiResultsDifs.end ())
1112  {
1113  rateFound = true;
1114  auto it = itDifs->second.find (n);
1115  if (it != itDifs->second.end ())
1116  {
1117  relativeErrorDifs = (std::abs (averageThroughput - it->second) / it->second);
1118  std::cout << "Relative error (DIFS): " << 100 * relativeErrorDifs << "%" << std::endl;
1119  }
1120  else if (validate)
1121  {
1122  NS_FATAL_ERROR ("No Bianchi results (DIFS) calculated for that number of stations!");
1123  }
1124  }
1125  auto itEifs = bianchiResultsEifs.find (static_cast<unsigned int> (phyRate * 1000000));
1126  if (itEifs != bianchiResultsEifs.end ())
1127  {
1128  rateFound = true;
1129  auto it = itEifs->second.find (n);
1130  if (it != itEifs->second.end ())
1131  {
1132  relativeErrorEifs = (std::abs (averageThroughput - it->second) / it->second);
1133  std::cout << "Relative error (EIFS): " << 100 * relativeErrorEifs << "%" << std::endl;
1134  }
1135  else if (validate)
1136  {
1137  NS_FATAL_ERROR ("No Bianchi results (EIFS) calculated for that number of stations!");
1138  }
1139  }
1140  if (!rateFound && validate)
1141  {
1142  NS_FATAL_ERROR ("No Bianchi results calculated for that rate!");
1143  }
1144  double relativeError = std::min (relativeErrorDifs, relativeErrorEifs);
1145  if (validate && (relativeError > maxRelativeError))
1146  {
1147  NS_FATAL_ERROR ("Relative error is too high!");
1148  }
1149 
1150  double stDev = 0;
1151  for (uint32_t i = 0; i < trials; ++i)
1152  {
1153  stDev += pow (throughputArray[i] - averageThroughput, 2);
1154  }
1155  stDev = sqrt (stDev / (trials - 1));
1156  dataset.Add (n, averageThroughput, stDev);
1157  }
1158  dataset.SetTitle ("ns-3");
1159 
1160  auto itDifs = bianchiResultsDifs.find (static_cast<unsigned int> (phyRate * 1000000));
1161  if (itDifs != bianchiResultsDifs.end ())
1162  {
1163  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1164  {
1165  double value = 0.0;
1166  auto it = itDifs->second.find (i);
1167  if (it != itDifs->second.end ())
1168  {
1169  value = it->second;
1170  }
1171  datasetBianchiDifs.Add (i, value);
1172  }
1173  }
1174  else
1175  {
1176  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1177  {
1178  datasetBianchiDifs.Add (i, 0.0);
1179  }
1180  }
1181 
1182  auto itEifs = bianchiResultsEifs.find (static_cast<unsigned int> (phyRate * 1000000));
1183  if (itEifs != bianchiResultsEifs.end ())
1184  {
1185  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1186  {
1187  double value = 0.0;
1188  auto it = itEifs->second.find (i);
1189  if (it != itEifs->second.end ())
1190  {
1191  value = it->second;
1192  }
1193  datasetBianchiEifs.Add (i, value);
1194  }
1195  }
1196  else
1197  {
1198  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1199  {
1200  datasetBianchiEifs.Add (i, 0.0);
1201  }
1202  }
1203 
1204  datasetBianchiEifs.SetTitle ("Bianchi (EIFS - lower bound)");
1205  datasetBianchiDifs.SetTitle ("Bianchi (DIFS - upper bound)");
1206  gnuplot.AddDataset (dataset);
1207  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
1208  gnuplot.SetLegend ("Number of competing stations", "Throughput (Mbps)");
1209  ss.str ("");
1210  ss << "Frame size " << pktSize << " bytes";
1211  gnuplot.SetTitle (ss.str ());
1212  ss.str ("");
1213  ss << "set xrange [" << nMinStas << ":" << nMaxStas << "]\n"
1214  << "set xtics " << nStepSize << "\n"
1215  << "set grid xtics ytics\n"
1216  << "set mytics\n"
1217  << "set style line 1 linewidth 5\n"
1218  << "set style line 2 linewidth 5\n"
1219  << "set style line 3 linewidth 5\n"
1220  << "set style line 4 linewidth 5\n"
1221  << "set style line 5 linewidth 5\n"
1222  << "set style line 6 linewidth 5\n"
1223  << "set style line 7 linewidth 5\n"
1224  << "set style line 8 linewidth 5\n"
1225  << "set style increment user";
1226  gnuplot.SetExtra (ss.str ());
1227  if (plotBianchiModel & 0x01)
1228  {
1229  datasetBianchiDifs.SetTitle ("Bianchi");
1230  gnuplot.AddDataset (datasetBianchiDifs);
1231  }
1232  if (plotBianchiModel & 0x02)
1233  {
1234  datasetBianchiEifs.SetTitle ("Bianchi");
1235  gnuplot.AddDataset (datasetBianchiEifs);
1236  }
1237  if (plotBianchiModel == 0x03)
1238  {
1239  datasetBianchiEifs.SetTitle ("Bianchi (EIFS - lower bound)");
1240  datasetBianchiDifs.SetTitle ("Bianchi (DIFS - upper bound)");
1241  }
1242  gnuplot.GenerateOutput (throughputPlot);
1243  throughputPlot.close ();
1244 
1245  if (tracing)
1246  {
1247  cwTraceFile.close ();
1248  backoffTraceFile.close ();
1249  phyTxTraceFile.close ();
1250  macTxTraceFile.close ();
1251  macRxTraceFile.close ();
1252  socketSendTraceFile.close ();
1253  }
1254 
1255  return 0;
1256 }
MpduInfo structure.
Definition: phy-entity.h:59
void AddPropagationLoss(std::string name, std::string n0="", const AttributeValue &v0=EmptyAttributeValue(), std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue(), std::string n5="", const AttributeValue &v5=EmptyAttributeValue(), std::string n6="", const AttributeValue &v6=EmptyAttributeValue(), std::string n7="", const AttributeValue &v7=EmptyAttributeValue())
Helper class for UAN CW MAC example.
Definition: wifi-adhoc.cc:40
holds a vector of ns3::Application pointers.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:159
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
void MacTxTrace(std::string context, Ptr< const Packet > p)
std::map< unsigned int, std::map< unsigned int, double > > bianchiResultsEifs
Definition: wifi-bianchi.cc:85
Class for representing queue sizes.
Definition: queue-size.h:94
void SetLocal(PacketSocketAddress addr)
set the local address and protocol to be used
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void IncrementCounter(std::map< Mac48Address, uint64_t > &counter, Mac48Address addr, uint64_t increment=1)
Class to represent a 2D points plot.
Definition: gnuplot.h:117
std::map< Mac48Address, Time > timeFirstReceived
Map that stores the time at which the first packet was received per STA (and the packet is addressed ...
Definition: wifi-bianchi.cc:75
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
void SetTitle(const std::string &title)
Change line title.
Definition: gnuplot.cc:141
Hold variables of type string.
Definition: string.h:41
static Ptr< Node > GetNode(uint32_t n)
Definition: node-list.cc:241
Make it easy to create and manage PHY objects for the YANS model.
#define min(a, b)
Definition: 80211b.c:42
std::map< unsigned int, std::map< unsigned int, double > > bianchiResultsDifs
std::map< Mac48Address, uint64_t > bytesReceived
Map that stores the total bytes received per STA (and addressed to that STA)
Definition: wifi-bianchi.cc:65
void DisassociationLog(std::string context, Mac48Address address)
std::ofstream macTxTraceFile
File that traces MAC transmissions over time.
Definition: wifi-bianchi.cc:60
def start()
Definition: core.py:1855
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
an address for a packet socket
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
Hold a signed integer type.
Definition: integer.h:44
void PhyRxOkTrace(std::string context, Ptr< const Packet > p, double snr, WifiMode mode, WifiPreamble preamble)
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
std::map< Mac48Address, Time > timeLastTransmitted
Map that stores the time at which the last packet was transmitted per STA.
Definition: wifi-bianchi.cc:78
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
Mac48Address ContextToMac(std::string context)
cmd
Definition: second.py:35
void AssociationLog(std::string context, Mac48Address address)
void PhyTxDoneTrace(std::string context, Ptr< const Packet > p)
void BackoffTrace(std::string context, uint32_t newVal)
helps to create WifiNetDevice objects
Definition: wifi-helper.h:326
void TracePacketReception(std::string context, Ptr< const Packet > packet, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise, uint16_t staId)
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:47
uint32_t ContextToNodeId(std::string context)
Give ns3::PacketSocket powers to ns3::Node.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Address GetAddress(void) const
a polymophic address class
Definition: address.h:90
Ptr< YansWifiChannel > Create(void) const
std::map< Mac48Address, uint64_t > phyHeaderFailed
Map that stores the total number of unsuccessfully received PHY headers per STA.
Definition: wifi-bianchi.cc:69
mobility
Definition: third.py:108
void SetErrorBars(enum ErrorBars errorBars)
Definition: gnuplot.cc:353
phy
Definition: third.py:93
#define PI
Definition: wifi-bianchi.cc:51
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
std::map< Mac48Address, uint64_t > rxEventWhileTxing
Map that stores the number of reception events per STA that occured while PHY was already transmittin...
Definition: wifi-bianchi.cc:70
std::map< Mac48Address, uint64_t > psduFailed
Map that stores the total number of unsuccessfully received PSDUS (for which the PHY header was succe...
Definition: wifi-bianchi.cc:67
void PhyRxDropTrace(std::string context, Ptr< const Packet > p, WifiPhyRxfailureReason reason)
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:73
void LogComponentEnable(char const *name, enum LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:361
uint64_t GetCount(const std::map< Mac48Address, uint64_t > &counter, Mac48Address addr)
a simple class to generate gnuplot-ready plotting commands from a set of datasets.
Definition: gnuplot.h:371
#define max(a, b)
Definition: 80211b.c:43
std::ofstream socketSendTraceFile
File that traces packets transmitted by the application over time.
Definition: wifi-bianchi.cc:62
AttributeValue implementation for Time.
Definition: nstime.h:1353
void MacRxTrace(std::string context, Ptr< const Packet > p)
Hold an unsigned integer type.
Definition: uinteger.h:44
double startTime
ssid
Definition: third.py:100
Use number of packets for queue size.
Definition: queue-size.h:44
holds a vector of ns3::NetDevice pointers
mac
Definition: third.py:99
void RestartCalc()
std::map< Mac48Address, uint64_t > packetsReceived
Map that stores the total packets received per STA (and addressed to that STA)
Definition: wifi-bianchi.cc:64
void PhyTxTrace(std::string context, Ptr< const Packet > p, double txPowerW)
Hold together all Wifi-related objects.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
std::map< Mac48Address, uint64_t > packetsTransmitted
Map that stores the total packets transmitted per STA.
Definition: wifi-bianchi.cc:66
void Add(double x, double y)
Definition: gnuplot.cc:359
void SocketSendTrace(std::string context, Ptr< const Packet > p, const Address &addr)
Parse command-line arguments.
Definition: command-line.h:227
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
static Mac48Address ConvertFrom(const Address &address)
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
uint32_t GetN(void) const
Get the number of Ptr<Node> stored in this container.
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:388
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:68
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetPhysicalAddress(const Address address)
Set the destination address.
WifiStandard
Identifies the allowed configurations that a Wifi device is configured to use.
keep track of a set of node pointers.
address
Definition: first.py:44
void CwTrace(std::string context, uint32_t oldVal, uint32_t newVal)
an EUI-48 address
Definition: mac48-address.h:43
manage and create wifi channel objects for the YANS model.
std::ofstream macRxTraceFile
File that traces MAC receptions over time.
Definition: wifi-bianchi.cc:61
void PhyRxDoneTrace(std::string context, Ptr< const Packet > p)
create MAC layers for a ns3::WifiNetDevice.
void SetStyle(enum Style style)
Definition: gnuplot.cc:342
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
void PhyRxTrace(std::string context, Ptr< const Packet > p, RxPowerWattPerChannelBand power)
void PhyRxPayloadTrace(std::string context, WifiTxVector txVector, Time psduDuration)
std::ofstream backoffTraceFile
File that traces backoff over time.
Definition: wifi-bianchi.cc:58
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:35
std::ofstream cwTraceFile
File that traces CW over time.
Definition: wifi-bianchi.cc:57
Gnuplot2dDataset Run(const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel)
Definition: wifi-adhoc.cc:119
void PhyRxErrorTrace(std::string context, Ptr< const Packet > p, double snr)
wifi
Definition: third.py:96
Helper class used to assign positions and mobility models to nodes.
std::set< uint32_t > associated
Contains the IDs of the STAs that successfully associated to the access point (in infrastructure mode...
Definition: wifi-bianchi.cc:80
static void EnableLogComponents(void)
Helper to enable all WifiNetDevice log components with one statement.
Definition: wifi-helper.cc:914
void experiment(std::string queue_disc_type)
std::map< Mac48Address, uint64_t > rxEventWhileRxing
Map that stores the number of reception events per STA that occured while PHY was already receiving a...
Definition: wifi-bianchi.cc:71
void SetRemote(PacketSocketAddress addr)
set the remote address and protocol to be used
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...
Definition: wifi-bianchi.cc:76
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
SignalNoiseDbm structure.
Definition: phy-entity.h:52
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
AttributeValue implementation for Ssid.
Definition: ssid.h:105
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void SetProtocol(uint16_t protocol)
Set the protocol.
void Add(Vector v)
Add a position to the list of positions.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
std::ofstream phyTxTraceFile
File that traces PHY transmissions over time.
Definition: wifi-bianchi.cc:59
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
Print everything.
Definition: log.h:116
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
std::map< Mac48Address, uint64_t > rxEventWhileDecodingPreamble
Map that stores the number of reception events per STA that occured while PHY was already decoding a ...
Definition: wifi-bianchi.cc:72
void SetPropagationDelay(std::string name, std::string n0="", const AttributeValue &v0=EmptyAttributeValue(), std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue(), std::string n5="", const AttributeValue &v5=EmptyAttributeValue(), std::string n6="", const AttributeValue &v6=EmptyAttributeValue(), std::string n7="", const AttributeValue &v7=EmptyAttributeValue())
devices
Definition: first.py:39
void DisablePreambleDetectionModel()
Disable the preamble detection model.
Definition: wifi-helper.cc:215
Definition: first.py:1
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:83
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
Include Radiotap link layer information.
Definition: wifi-helper.h:180
void SetStartTime(Time start)
Specify application start time.
Definition: application.cc:69
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
bool tracing
Flag to enable/disable generation of tracing files.
Definition: wifi-bianchi.cc:82
std::map< WifiSpectrumBand, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:75
Implements the IEEE 802.11 MAC header.
bool verbose
std::map< Mac48Address, Time > timeFirstTransmitted
Map that stores the time at which the first packet was transmitted per STA.
Definition: wifi-bianchi.cc:77