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)
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
483 PhyRxTrace (std::string context, Ptr<const Packet> p)
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 SIG_A_FAILURE:
554  NS_FATAL_ERROR ("Unexpected PHY header failure!");
556  NS_FATAL_ERROR ("All devices should send with same power, so no packet switch during preamble detection should occur!");
557  break;
559  NS_FATAL_ERROR ("Frame capture should be disabled!");
560  break;
561  case OBSS_PD_CCA_RESET:
562  NS_FATAL_ERROR ("Unexpected CCA reset!");
563  break;
564  case UNKNOWN:
565  default:
566  NS_FATAL_ERROR ("Unknown drop reason!");
567  break;
568  }
569 }
570 
571 void
572 PhyRxDoneTrace (std::string context, Ptr<const Packet> p)
573 {
574  NS_LOG_INFO ("PHY-RX-END time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize ());
575 }
576 
577 void
578 PhyRxOkTrace (std::string context, Ptr<const Packet> p, double snr, WifiMode mode, WifiPreamble preamble)
579 {
580  NS_LOG_INFO ("PHY-RX-OK time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize () << " snr=" << snr << " mode=" << mode << " preamble=" << preamble);
581  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
582  {
583  Mac48Address addr = ContextToMac (context);
585  }
586 }
587 
588 void
589 PhyRxErrorTrace (std::string context, Ptr<const Packet> p, double snr)
590 {
591  NS_LOG_INFO ("PHY-RX-ERROR time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize () << " snr=" << snr);
592  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
593  {
594  Mac48Address addr = ContextToMac (context);
596  }
597 }
598 
599 void
600 PhyTxTrace (std::string context, Ptr<const Packet> p, double txPowerW)
601 {
602  NS_LOG_INFO ("PHY-TX-START time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " size=" << p->GetSize () << " " << txPowerW);
603  if (tracing)
604  {
605  phyTxTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " size=" << p->GetSize () << " " << txPowerW << std::endl;
606  }
607  if (p->GetSize () == (pktSize + 36)) // ignore non-data frames
608  {
609  Mac48Address addr = ContextToMac (context);
611  }
612 }
613 
614 void
615 PhyTxDoneTrace (std::string context, Ptr<const Packet> p)
616 {
617  NS_LOG_INFO ("PHY-TX-END time=" << Simulator::Now () << " node=" << ContextToNodeId (context) << " " << p->GetSize ());
618 }
619 
620 void
621 MacTxTrace (std::string context, Ptr<const Packet> p)
622 {
623  if (tracing)
624  {
625  macTxTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << p->GetSize () << std::endl;
626  }
627 }
628 
629 void
630 MacRxTrace (std::string context, Ptr<const Packet> p)
631 {
632  if (tracing)
633  {
634  macRxTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << p->GetSize () << std::endl;
635  }
636 }
637 
638 void
639 SocketSendTrace (std::string context, Ptr<const Packet> p, const Address &addr)
640 {
641  if (tracing)
642  {
643  socketSendTraceFile << Simulator::Now ().GetSeconds () << " " << ContextToNodeId (context) << " " << p->GetSize () << " " << addr << std::endl;
644  }
645 }
646 
647 void
648 AssociationLog (std::string context, Mac48Address address)
649 {
650  uint32_t nodeId = ContextToNodeId (context);
651  auto it = associated.find (nodeId);
652  if (it == associated.end ())
653  {
654  NS_LOG_DEBUG ("Association: time=" << Simulator::Now () << " node=" << nodeId);
655  associated.insert (it, nodeId);
656  }
657  else
658  {
659  NS_FATAL_ERROR (nodeId << " is already associated!");
660  }
661 }
662 
663 void
664 DisassociationLog (std::string context, Mac48Address address)
665 {
666  uint32_t nodeId = ContextToNodeId (context);
667  NS_LOG_DEBUG ("Disassociation: time=" << Simulator::Now () << " node=" << nodeId);
668  NS_FATAL_ERROR ("Device should not disassociate!");
669 }
670 
671 void
673 {
674  bytesReceived.clear ();
675  packetsReceived.clear ();
676  packetsTransmitted.clear ();
677  psduFailed.clear ();
678  psduSucceeded.clear ();
679  phyHeaderFailed.clear ();
680  timeFirstReceived.clear ();
681  timeLastReceived.clear ();
683  rxEventWhileRxing.clear ();
684  rxEventWhileTxing.clear ();
685  rxEventAbortedByTx.clear ();
686 }
687 
688 class Experiment
689 {
690 public:
691  Experiment ();
692  int Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel,
693  uint32_t trialNumber, uint32_t networkSize, double duration, bool pcap, bool infra);
694 };
695 
697 {
698 }
699 
700 int
701 Experiment::Run (const WifiHelper &helper, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel,
702  uint32_t trialNumber, uint32_t networkSize, double duration, bool pcap, bool infra)
703 {
704  NodeContainer wifiNodes;
705  if (infra)
706  {
707  wifiNodes.Create (networkSize + 1);
708  }
709  else
710  {
711  wifiNodes.Create (networkSize);
712  }
713 
714  YansWifiPhyHelper phy = wifiPhy;
715  phy.SetChannel (wifiChannel.Create ());
716  phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
717 
718  WifiMacHelper mac = wifiMac;
719  WifiHelper wifi = helper;
721  uint32_t nNodes = wifiNodes.GetN ();
722  if (infra)
723  {
724  Ssid ssid = Ssid ("wifi-bianchi");
725  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)
726  mac.SetType ("ns3::ApWifiMac",
727  "BeaconInterval", TimeValue (MicroSeconds (beaconInterval)),
728  "Ssid", SsidValue (ssid));
729  devices = wifi.Install (phy, mac, wifiNodes.Get (0));
730 
731  mac.SetType ("ns3::StaWifiMac",
732  "MaxMissedBeacons", UintegerValue (std::numeric_limits<uint32_t>::max ()),
733  "Ssid", SsidValue (ssid));
734  for (uint32_t i = 1; i < nNodes; ++i)
735  {
736  devices.Add (wifi.Install (phy, mac, wifiNodes.Get (i)));
737  }
738  }
739  else
740  {
741  mac.SetType ("ns3::AdhocWifiMac");
742  devices = wifi.Install (phy, mac, wifiNodes);
743  }
744 
745  wifi.AssignStreams (devices, trialNumber);
746 
748  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
749  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
750  // Set postion for AP
751  positionAlloc->Add (Vector (1.0, 1.0, 0.0));
752 
753  // Set postion for STAs
754  double angle = (static_cast<double> (360) / (nNodes - 1));
755  for (uint32_t i = 0; i < (nNodes - 1); ++i)
756  {
757  positionAlloc->Add (Vector (1.0 + (0.001 * cos ((i * angle * PI) / 180)), 1.0 + (0.001 * sin ((i * angle * PI) / 180)), 0.0));
758  }
759 
760  mobility.SetPositionAllocator (positionAlloc);
761  mobility.Install (wifiNodes);
762 
763  PacketSocketHelper packetSocket;
764  packetSocket.Install (wifiNodes);
765 
767  Ptr<UniformRandomVariable> startTime = CreateObject<UniformRandomVariable> ();
768  startTime->SetAttribute ("Stream", IntegerValue (trialNumber));
769  startTime->SetAttribute ("Max", DoubleValue (5.0));
770 
771  uint32_t i = infra ? 1 : 0;
772  for (; i < nNodes; ++i)
773  {
774  uint32_t j = infra ? 0 : (i + 1) % nNodes;
775  PacketSocketAddress socketAddr;
776  socketAddr.SetSingleDevice (devices.Get (i)->GetIfIndex ());
777  socketAddr.SetPhysicalAddress (devices.Get (j)->GetAddress ());
778  socketAddr.SetProtocol (1);
779 
780  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient> ();
781  client->SetRemote (socketAddr);
782  wifiNodes.Get (i)->AddApplication (client);
783  client->SetAttribute ("PacketSize", UintegerValue (pktSize));
784  client->SetAttribute ("MaxPackets", UintegerValue (0));
785  client->SetAttribute ("Interval", TimeValue (MilliSeconds (1))); //TODO: reduce it for lower rates, increase it for higher rates
786  double start = startTime->GetValue ();
787  NS_LOG_DEBUG ("Client " << i << " starting at " << start);
788  client->SetStartTime (Seconds (start));
789 
790  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
791  server->SetLocal (socketAddr);
792  wifiNodes.Get (j)->AddApplication (server);
793  }
794 
795  // Log packet receptions
796  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/MonitorSnifferRx", MakeCallback (&TracePacketReception));
797 
798  // Log association and disassociation
799  if (infra)
800  {
801  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/Assoc", MakeCallback (&AssociationLog));
802  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/DeAssoc", MakeCallback (&DisassociationLog));
803  }
804 
805  // Trace CW evolution
806  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::RegularWifiMac/Txop/CwTrace", MakeCallback (&CwTrace));
807  // Trace backoff evolution
808  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::RegularWifiMac/Txop/BackoffTrace", MakeCallback (&BackoffTrace));
809  // Trace PHY Tx start events
810  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxBegin", MakeCallback (&PhyTxTrace));
811  // Trace PHY Tx end events
812  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxEnd", MakeCallback (&PhyTxDoneTrace));
813  // Trace PHY Rx start events
814  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxBegin", MakeCallback (&PhyRxTrace));
815  // Trace PHY Rx payload start events
816  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxPayloadBegin", MakeCallback (&PhyRxPayloadTrace));
817  // Trace PHY Rx drop events
818  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxDrop", MakeCallback (&PhyRxDropTrace));
819  // Trace PHY Rx end events
820  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxEnd", MakeCallback (&PhyRxDoneTrace));
821  // Trace PHY Rx error events
822  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxError", MakeCallback (&PhyRxErrorTrace));
823  // Trace PHY Rx success events
824  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxOk", MakeCallback (&PhyRxOkTrace));
825  // Trace packet transmission by the device
826  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx", MakeCallback (&MacTxTrace));
827  // Trace packet receptions to the device
828  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx", MakeCallback (&MacRxTrace));
829  // Trace packets transmitted by the application
830  Config::Connect ("/NodeList/*/$ns3::Node/ApplicationList/*/$ns3::PacketSocketClient/Tx", MakeCallback (&SocketSendTrace));
831 
833  Simulator::Stop (Seconds (10 + duration));
834 
835  if (pcap)
836  {
837  phy.EnablePcap ("wifi_bianchi_pcap", devices);
838  }
839 
840  Simulator::Run ();
842 
843  if (tracing)
844  {
845  cwTraceFile.flush ();
846  backoffTraceFile.flush ();
847  phyTxTraceFile.flush ();
848  macTxTraceFile.flush ();
849  macRxTraceFile.flush ();
850  socketSendTraceFile.flush ();
851  }
852 
853  return 0;
854 }
855 
856 uint64_t
857 GetCount (const std::map<Mac48Address, uint64_t> & counter, Mac48Address addr)
858 {
859  uint64_t count = 0;
860  auto it = counter.find (addr);
861  if (it != counter.end ())
862  {
863  count = it->second;
864  }
865  return count;
866 }
867 
868 int main (int argc, char *argv[])
869 {
870  uint32_t nMinStas = 5;
871  uint32_t nMaxStas = 50;
872  uint32_t nStepSize = 5;
873  uint32_t verbose = 0;
874  double duration = 100;
875  uint32_t trials = 1;
876  bool pcap = false;
877  bool infra = false;
878  std::string workDir = "./";
879  double phyRate = 54;
880  std::string standard ("11a");
881  bool validate = false;
882  uint32_t plotBianchiModel = 0x1;
883  double maxRelativeError = 0.015;
884 
885  // Disable fragmentation and RTS/CTS
886  Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("22000"));
887  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("22000"));
888  // Disable short retransmission failure (make retransmissions persistent)
889  Config::SetDefault ("ns3::WifiRemoteStationManager::MaxSlrc", UintegerValue (std::numeric_limits<uint32_t>::max ()));
890  Config::SetDefault ("ns3::WifiRemoteStationManager::MaxSsrc", UintegerValue (std::numeric_limits<uint32_t>::max ()));
891  // Set maximum queue size to the largest value and set maximum queue delay to be larger than the simulation time
893  Config::SetDefault ("ns3::WifiMacQueue::MaxDelay", TimeValue (Seconds (2 * duration)));
894 
895  CommandLine cmd (__FILE__);
896  cmd.AddValue ("verbose", "Logging level (0: no log - 1: simulation script logs - 2: all logs)", verbose);
897  cmd.AddValue ("tracing", "Generate trace files", tracing);
898  cmd.AddValue ("pktSize", "The packet size in bytes", pktSize);
899  cmd.AddValue ("trials", "The maximal number of runs per network size", trials);
900  cmd.AddValue ("duration", "Time duration for each trial in seconds", duration);
901  cmd.AddValue ("pcap", "Enable/disable PCAP tracing", pcap);
902  cmd.AddValue ("infra", "True to use infrastructure mode, false to use ring adhoc mode", infra);
903  cmd.AddValue ("workDir", "The working directory used to store generated files", workDir);
904  cmd.AddValue ("phyRate", "Set the constant PHY rate in Mbps used to transmit Data frames", phyRate);
905  cmd.AddValue ("standard", "Set the standard (11a, 11b, 11g, 11n, 11ac, 11ax)", standard);
906  cmd.AddValue ("nMinStas", "Minimum number of stations to start with", nMinStas);
907  cmd.AddValue ("nMaxStas", "Maximum number of stations to start with", nMaxStas);
908  cmd.AddValue ("nStepSize", "Number of stations to add at each step", nStepSize);
909  cmd.AddValue ("validate", "Enable/disable validation of the ns-3 simulations against the Bianchi model", validate);
910  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);
911  cmd.Parse (argc, argv);
912 
913  if (tracing)
914  {
915  cwTraceFile.open ("wifi-bianchi-cw-trace.out");
916  if (!cwTraceFile.is_open ())
917  {
918  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-cw-trace.out");
919  }
920  backoffTraceFile.open ("wifi-bianchi-backoff-trace.out");
921  if (!backoffTraceFile.is_open ())
922  {
923  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-backoff-trace.out");
924  }
925  phyTxTraceFile.open ("wifi-bianchi-phy-tx-trace.out");
926  if (!phyTxTraceFile.is_open ())
927  {
928  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-phy-tx-trace.out");
929  }
930  macTxTraceFile.open ("wifi-bianchi-mac-tx-trace.out");
931  if (!macTxTraceFile.is_open ())
932  {
933  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-mac-tx-trace.out");
934  }
935  macRxTraceFile.open ("wifi-bianchi-mac-rx-trace.out");
936  if (!macRxTraceFile.is_open ())
937  {
938  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-mac-rx-trace.out");
939  }
940  socketSendTraceFile.open ("wifi-bianchi-socket-send-trace.out");
941  if (!socketSendTraceFile.is_open ())
942  {
943  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-socket-send-trace.out");
944  }
945  }
946 
947  if (verbose >= 1)
948  {
949  LogComponentEnable ("WifiBianchi", LOG_LEVEL_ALL);
950  }
951  if (verbose >= 2)
952  {
954  }
955 
956  std::stringstream ss;
957  ss << "wifi-"<< standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") << "-r-" << phyRate << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize << "-throughput.plt";
958  std::ofstream throughputPlot (ss.str ().c_str ());
959  ss.str ("");
960  ss << "wifi-" << standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") <<"-r-" << phyRate << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize << "-throughput.eps";
961  Gnuplot gnuplot = Gnuplot (ss.str ());
962 
963  WifiStandard wifiStandard;
964  std::stringstream phyRateStr;
965  if (standard == "11a")
966  {
967  wifiStandard = WIFI_STANDARD_80211a;
968  if ((phyRate != 6) && (phyRate != 9) && (phyRate != 12) && (phyRate != 18) && (phyRate != 24) && (phyRate != 36) && (phyRate != 48) && (phyRate != 54))
969  {
970  NS_FATAL_ERROR ("Selected PHY rate " << phyRate << " is not defined in " << standard);
971  }
972  phyRateStr << "OfdmRate" << phyRate << "Mbps";
973  }
974  else if (standard == "11b")
975  {
976  wifiStandard = WIFI_STANDARD_80211b;
977  if ((phyRate != 1) && (phyRate != 2) && (phyRate != 5.5) && (phyRate != 11))
978  {
979  NS_FATAL_ERROR ("Selected PHY rate " << phyRate << " is not defined in " << standard);
980  }
981  if (phyRate == 5.5)
982  {
983  phyRateStr << "DsssRate5_5Mbps";
984  }
985  else
986  {
987  phyRateStr << "DsssRate" << phyRate << "Mbps";
988  }
989  }
990  else if (standard == "11g")
991  {
992  wifiStandard = WIFI_STANDARD_80211g;
993  if ((phyRate != 6) && (phyRate != 9) && (phyRate != 12) && (phyRate != 18) && (phyRate != 24) && (phyRate != 36) && (phyRate != 48) && (phyRate != 54))
994  {
995  NS_FATAL_ERROR ("Selected PHY rate " << phyRate << " is not defined in " << standard);
996  }
997  phyRateStr << "ErpOfdmRate" << phyRate << "Mbps";
998  }
999  else
1000  {
1001  NS_FATAL_ERROR ("Unsupported standard: " << standard);
1002  }
1003 
1005  YansWifiChannelHelper wifiChannel;
1006  wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
1007  wifiChannel.AddPropagationLoss ("ns3::LogDistancePropagationLossModel");
1008  wifiPhy.DisablePreambleDetectionModel ();
1009 
1010  WifiMacHelper wifiMac;
1011 
1012  WifiHelper wifi;
1013  wifi.SetStandard (wifiStandard);
1014  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue (phyRateStr.str()));
1015 
1016  Gnuplot2dDataset dataset;
1017  Gnuplot2dDataset datasetBianchiEifs;
1018  Gnuplot2dDataset datasetBianchiDifs;
1021  datasetBianchiEifs.SetStyle (Gnuplot2dDataset::LINES_POINTS);
1022  datasetBianchiDifs.SetStyle (Gnuplot2dDataset::LINES_POINTS);
1023 
1025  double averageThroughput, throughputArray[trials];
1026  for (uint32_t n = nMinStas; n <= nMaxStas; n += nStepSize)
1027  {
1028  averageThroughput = 0;
1029  double throughput;
1030  for (uint32_t runIndex = 0; runIndex < trials; runIndex++)
1031  {
1032  packetsReceived.clear ();
1033  bytesReceived.clear ();
1034  packetsTransmitted.clear ();
1035  psduFailed.clear ();
1036  psduSucceeded.clear ();
1037  phyHeaderFailed.clear ();
1038  timeFirstReceived.clear ();
1039  timeLastReceived.clear ();
1041  rxEventWhileRxing.clear ();
1042  rxEventWhileTxing.clear ();
1043  rxEventAbortedByTx.clear ();
1044  associated.clear ();
1045  throughput = 0;
1046  std::cout << "Trial " << runIndex + 1 << " of " << trials << "; "<< phyRate << " Mbps for " << n << " nodes " << std::endl;
1047  if (tracing)
1048  {
1049  cwTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "<< phyRate << " Mbps for " << n << " nodes" << std::endl;
1050  backoffTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "<< phyRate << " Mbps for " << n << " nodes" << std::endl;
1051  phyTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1052  macTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1053  macRxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1054  socketSendTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1055  }
1056  experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, runIndex, n, duration, pcap, infra);
1057  uint32_t k = 0;
1058  if (bytesReceived.size () != n)
1059  {
1060  NS_FATAL_ERROR ("Not all stations got traffic!");
1061  }
1062  for (auto it = bytesReceived.begin (); it != bytesReceived.end (); it++, k++)
1063  {
1064  Time first = timeFirstReceived.find (it->first)->second;
1065  Time last = timeLastReceived.find (it->first)->second;
1066  Time dataTransferDuration = last - first;
1067  double nodeThroughput = (it->second * 8 / static_cast<double> (dataTransferDuration.GetMicroSeconds ()));
1068  throughput += nodeThroughput;
1069  uint64_t nodeTxPackets = GetCount (packetsTransmitted, it->first);
1070  uint64_t nodeRxPackets = GetCount (packetsReceived, it->first);
1071  uint64_t nodePhyHeaderFailures = GetCount (phyHeaderFailed, it->first);
1072  uint64_t nodePsduFailures = GetCount (psduFailed, it->first);
1073  uint64_t nodePsduSuccess = GetCount (psduSucceeded, it->first);
1074  uint64_t nodeRxEventWhileDecodingPreamble = GetCount (rxEventWhileDecodingPreamble, it->first);
1075  uint64_t nodeRxEventWhileRxing = GetCount (rxEventWhileRxing, it->first);
1076  uint64_t nodeRxEventWhileTxing = GetCount (rxEventWhileTxing, it->first);
1077  uint64_t nodeRxEventAbortedByTx = GetCount (rxEventAbortedByTx, it->first);
1078  uint64_t nodeRxEvents =
1079  nodePhyHeaderFailures + nodePsduFailures + nodePsduSuccess + nodeRxEventWhileDecodingPreamble +
1080  nodeRxEventWhileRxing + nodeRxEventWhileTxing + nodeRxEventAbortedByTx;
1081  std::cout << "Node " << it->first
1082  << ": TX packets " << nodeTxPackets
1083  << "; RX packets " << nodeRxPackets
1084  << "; PHY header failures " << nodePhyHeaderFailures
1085  << "; PSDU failures " << nodePsduFailures
1086  << "; PSDU success " << nodePsduSuccess
1087  << "; RX events while decoding preamble " << nodeRxEventWhileDecodingPreamble
1088  << "; RX events while RXing " << nodeRxEventWhileRxing
1089  << "; RX events while TXing " << nodeRxEventWhileTxing
1090  << "; RX events aborted by TX " << nodeRxEventAbortedByTx
1091  << "; total RX events " << nodeRxEvents
1092  << "; total events " << nodeTxPackets + nodeRxEvents
1093  << "; time first RX " << first
1094  << "; time last RX " << last
1095  << "; dataTransferDuration " << dataTransferDuration
1096  << "; throughput " << nodeThroughput << " Mbps" << std::endl;
1097  }
1098  std::cout << "Total throughput: " << throughput << " Mbps" << std::endl;
1099  averageThroughput += throughput;
1100  throughputArray[runIndex] = throughput;
1101  }
1102  averageThroughput = averageThroughput / trials;
1103 
1104  bool rateFound = false;
1105  double relativeErrorDifs = 0;
1106  double relativeErrorEifs = 0;
1107  auto itDifs = bianchiResultsDifs.find (static_cast<unsigned int> (phyRate * 1000000));
1108  if (itDifs != bianchiResultsDifs.end ())
1109  {
1110  rateFound = true;
1111  auto it = itDifs->second.find (n);
1112  if (it != itDifs->second.end ())
1113  {
1114  relativeErrorDifs = (std::abs (averageThroughput - it->second) / it->second);
1115  std::cout << "Relative error (DIFS): " << 100 * relativeErrorDifs << "%" << std::endl;
1116  }
1117  else if (validate)
1118  {
1119  NS_FATAL_ERROR ("No Bianchi results (DIFS) calculated for that number of stations!");
1120  }
1121  }
1122  auto itEifs = bianchiResultsEifs.find (static_cast<unsigned int> (phyRate * 1000000));
1123  if (itEifs != bianchiResultsEifs.end ())
1124  {
1125  rateFound = true;
1126  auto it = itEifs->second.find (n);
1127  if (it != itEifs->second.end ())
1128  {
1129  relativeErrorEifs = (std::abs (averageThroughput - it->second) / it->second);
1130  std::cout << "Relative error (EIFS): " << 100 * relativeErrorEifs << "%" << std::endl;
1131  }
1132  else if (validate)
1133  {
1134  NS_FATAL_ERROR ("No Bianchi results (EIFS) calculated for that number of stations!");
1135  }
1136  }
1137  if (!rateFound && validate)
1138  {
1139  NS_FATAL_ERROR ("No Bianchi results calculated for that rate!");
1140  }
1141  double relativeError = std::min (relativeErrorDifs, relativeErrorEifs);
1142  if (validate && (relativeError > maxRelativeError))
1143  {
1144  NS_FATAL_ERROR ("Relative error is too high!");
1145  }
1146 
1147  double stDev = 0;
1148  for (uint32_t i = 0; i < trials; ++i)
1149  {
1150  stDev += pow (throughputArray[i] - averageThroughput, 2);
1151  }
1152  stDev = sqrt (stDev / (trials - 1));
1153  dataset.Add (n, averageThroughput, stDev);
1154  }
1155  dataset.SetTitle ("ns-3");
1156 
1157  auto itDifs = bianchiResultsDifs.find (static_cast<unsigned int> (phyRate * 1000000));
1158  if (itDifs != bianchiResultsDifs.end ())
1159  {
1160  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1161  {
1162  double value = 0.0;
1163  auto it = itDifs->second.find (i);
1164  if (it != itDifs->second.end ())
1165  {
1166  value = it->second;
1167  }
1168  datasetBianchiDifs.Add (i, value);
1169  }
1170  }
1171  else
1172  {
1173  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1174  {
1175  datasetBianchiDifs.Add (i, 0.0);
1176  }
1177  }
1178 
1179  auto itEifs = bianchiResultsEifs.find (static_cast<unsigned int> (phyRate * 1000000));
1180  if (itEifs != bianchiResultsEifs.end ())
1181  {
1182  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1183  {
1184  double value = 0.0;
1185  auto it = itEifs->second.find (i);
1186  if (it != itEifs->second.end ())
1187  {
1188  value = it->second;
1189  }
1190  datasetBianchiEifs.Add (i, value);
1191  }
1192  }
1193  else
1194  {
1195  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1196  {
1197  datasetBianchiEifs.Add (i, 0.0);
1198  }
1199  }
1200 
1201  datasetBianchiEifs.SetTitle ("Bianchi (EIFS - lower bound)");
1202  datasetBianchiDifs.SetTitle ("Bianchi (DIFS - upper bound)");
1203  gnuplot.AddDataset (dataset);
1204  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
1205  gnuplot.SetLegend ("Number of competing stations", "Throughput (Mbps)");
1206  ss.str ("");
1207  ss << "Frame size " << pktSize << " bytes";
1208  gnuplot.SetTitle (ss.str ());
1209  ss.str ("");
1210  ss << "set xrange [" << nMinStas << ":" << nMaxStas << "]\n"
1211  << "set xtics " << nStepSize << "\n"
1212  << "set grid xtics ytics\n"
1213  << "set mytics\n"
1214  << "set style line 1 linewidth 5\n"
1215  << "set style line 2 linewidth 5\n"
1216  << "set style line 3 linewidth 5\n"
1217  << "set style line 4 linewidth 5\n"
1218  << "set style line 5 linewidth 5\n"
1219  << "set style line 6 linewidth 5\n"
1220  << "set style line 7 linewidth 5\n"
1221  << "set style line 8 linewidth 5\n"
1222  << "set style increment user";
1223  gnuplot.SetExtra (ss.str ());
1224  if (plotBianchiModel & 0x01)
1225  {
1226  datasetBianchiDifs.SetTitle ("Bianchi");
1227  gnuplot.AddDataset (datasetBianchiDifs);
1228  }
1229  if (plotBianchiModel & 0x02)
1230  {
1231  datasetBianchiEifs.SetTitle ("Bianchi");
1232  gnuplot.AddDataset (datasetBianchiEifs);
1233  }
1234  if (plotBianchiModel == 0x03)
1235  {
1236  datasetBianchiEifs.SetTitle ("Bianchi (EIFS - lower bound)");
1237  datasetBianchiDifs.SetTitle ("Bianchi (DIFS - upper bound)");
1238  }
1239  gnuplot.GenerateOutput (throughputPlot);
1240  throughputPlot.close ();
1241 
1242  if (tracing)
1243  {
1244  cwTraceFile.close ();
1245  backoffTraceFile.close ();
1246  phyTxTraceFile.close ();
1247  macTxTraceFile.close ();
1248  macRxTraceFile.close ();
1249  socketSendTraceFile.close ();
1250  }
1251 
1252  return 0;
1253 }
MpduInfo structure.
Definition: wifi-phy.h:123
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:379
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)
#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:1286
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
static YansWifiPhyHelper Default(void)
Create a PHY helper in a default working state.
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:318
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
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.
Definition: wifi-preamble.h:32
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:1342
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:226
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:918
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:387
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
void TracePacketReception(std::string context, Ptr< const Packet > packet, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise)
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 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:924
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: wifi-phy.h:116
#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:1278
AttributeValue implementation for Ssid.
Definition: ssid.h:105
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
Definition: wifi-phy.h:52
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:1294
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:218
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
void PhyRxTrace(std::string context, Ptr< const Packet > p)
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
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