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 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.SetErrorRateModel ("ns3::NistErrorRateModel");
716  phy.SetChannel (wifiChannel.Create ());
717  phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
718 
719  WifiMacHelper mac = wifiMac;
720  WifiHelper wifi = helper;
722  uint32_t nNodes = wifiNodes.GetN ();
723  if (infra)
724  {
725  Ssid ssid = Ssid ("wifi-bianchi");
726  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)
727  mac.SetType ("ns3::ApWifiMac",
728  "BeaconInterval", TimeValue (MicroSeconds (beaconInterval)),
729  "Ssid", SsidValue (ssid));
730  devices = wifi.Install (phy, mac, wifiNodes.Get (0));
731 
732  mac.SetType ("ns3::StaWifiMac",
733  "MaxMissedBeacons", UintegerValue (std::numeric_limits<uint32_t>::max ()),
734  "Ssid", SsidValue (ssid));
735  for (uint32_t i = 1; i < nNodes; ++i)
736  {
737  devices.Add (wifi.Install (phy, mac, wifiNodes.Get (i)));
738  }
739  }
740  else
741  {
742  mac.SetType ("ns3::AdhocWifiMac");
743  devices = wifi.Install (phy, mac, wifiNodes);
744  }
745 
746  wifi.AssignStreams (devices, trialNumber);
747 
749  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
750  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
751  // Set postion for AP
752  positionAlloc->Add (Vector (1.0, 1.0, 0.0));
753 
754  // Set postion for STAs
755  double angle = (static_cast<double> (360) / (nNodes - 1));
756  for (uint32_t i = 0; i < (nNodes - 1); ++i)
757  {
758  positionAlloc->Add (Vector (1.0 + (0.001 * cos ((i * angle * PI) / 180)), 1.0 + (0.001 * sin ((i * angle * PI) / 180)), 0.0));
759  }
760 
761  mobility.SetPositionAllocator (positionAlloc);
762  mobility.Install (wifiNodes);
763 
764  PacketSocketHelper packetSocket;
765  packetSocket.Install (wifiNodes);
766 
768  Ptr<UniformRandomVariable> startTime = CreateObject<UniformRandomVariable> ();
769  startTime->SetAttribute ("Stream", IntegerValue (trialNumber));
770  startTime->SetAttribute ("Max", DoubleValue (5.0));
771 
772  uint32_t i = infra ? 1 : 0;
773  for (; i < nNodes; ++i)
774  {
775  uint32_t j = infra ? 0 : (i + 1) % nNodes;
776  PacketSocketAddress socketAddr;
777  socketAddr.SetSingleDevice (devices.Get (i)->GetIfIndex ());
778  socketAddr.SetPhysicalAddress (devices.Get (j)->GetAddress ());
779  socketAddr.SetProtocol (1);
780 
781  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient> ();
782  client->SetRemote (socketAddr);
783  wifiNodes.Get (i)->AddApplication (client);
784  client->SetAttribute ("PacketSize", UintegerValue (pktSize));
785  client->SetAttribute ("MaxPackets", UintegerValue (0));
786  client->SetAttribute ("Interval", TimeValue (MilliSeconds (1))); //TODO: reduce it for lower rates, increase it for higher rates
787  double start = startTime->GetValue ();
788  NS_LOG_DEBUG ("Client " << i << " starting at " << start);
789  client->SetStartTime (Seconds (start));
790 
791  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
792  server->SetLocal (socketAddr);
793  wifiNodes.Get (j)->AddApplication (server);
794  }
795 
796  // Log packet receptions
797  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/MonitorSnifferRx", MakeCallback (&TracePacketReception));
798 
799  // Log association and disassociation
800  if (infra)
801  {
802  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/Assoc", MakeCallback (&AssociationLog));
803  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/DeAssoc", MakeCallback (&DisassociationLog));
804  }
805 
806  // Trace CW evolution
807  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::RegularWifiMac/Txop/CwTrace", MakeCallback (&CwTrace));
808  // Trace backoff evolution
809  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::RegularWifiMac/Txop/BackoffTrace", MakeCallback (&BackoffTrace));
810  // Trace PHY Tx start events
811  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxBegin", MakeCallback (&PhyTxTrace));
812  // Trace PHY Tx end events
813  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxEnd", MakeCallback (&PhyTxDoneTrace));
814  // Trace PHY Rx start events
815  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxBegin", MakeCallback (&PhyRxTrace));
816  // Trace PHY Rx payload start events
817  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxPayloadBegin", MakeCallback (&PhyRxPayloadTrace));
818  // Trace PHY Rx drop events
819  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxDrop", MakeCallback (&PhyRxDropTrace));
820  // Trace PHY Rx end events
821  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxEnd", MakeCallback (&PhyRxDoneTrace));
822  // Trace PHY Rx error events
823  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxError", MakeCallback (&PhyRxErrorTrace));
824  // Trace PHY Rx success events
825  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxOk", MakeCallback (&PhyRxOkTrace));
826  // Trace packet transmission by the device
827  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx", MakeCallback (&MacTxTrace));
828  // Trace packet receptions to the device
829  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx", MakeCallback (&MacRxTrace));
830  // Trace packets transmitted by the application
831  Config::Connect ("/NodeList/*/$ns3::Node/ApplicationList/*/$ns3::PacketSocketClient/Tx", MakeCallback (&SocketSendTrace));
832 
834  Simulator::Stop (Seconds (10 + duration));
835 
836  if (pcap)
837  {
838  phy.EnablePcap ("wifi_bianchi_pcap", devices);
839  }
840 
841  Simulator::Run ();
843 
844  if (tracing)
845  {
846  cwTraceFile.flush ();
847  backoffTraceFile.flush ();
848  phyTxTraceFile.flush ();
849  macTxTraceFile.flush ();
850  macRxTraceFile.flush ();
851  socketSendTraceFile.flush ();
852  }
853 
854  return 0;
855 }
856 
857 uint64_t
858 GetCount (const std::map<Mac48Address, uint64_t> & counter, Mac48Address addr)
859 {
860  uint64_t count = 0;
861  auto it = counter.find (addr);
862  if (it != counter.end ())
863  {
864  count = it->second;
865  }
866  return count;
867 }
868 
869 int main (int argc, char *argv[])
870 {
871  uint32_t nMinStas = 5;
872  uint32_t nMaxStas = 50;
873  uint32_t nStepSize = 5;
874  uint32_t verbose = 0;
875  double duration = 100;
876  uint32_t trials = 1;
877  bool pcap = false;
878  bool infra = false;
879  std::string workDir = "./";
880  double phyRate = 54;
881  std::string standard ("11a");
882  bool validate = false;
883  uint32_t plotBianchiModel = 0x1;
884  double maxRelativeError = 0.015;
885 
886  // Disable fragmentation and RTS/CTS
887  Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("22000"));
888  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("22000"));
889  // Disable short retransmission failure (make retransmissions persistent)
890  Config::SetDefault ("ns3::WifiRemoteStationManager::MaxSlrc", UintegerValue (std::numeric_limits<uint32_t>::max ()));
891  Config::SetDefault ("ns3::WifiRemoteStationManager::MaxSsrc", UintegerValue (std::numeric_limits<uint32_t>::max ()));
892  // Set maximum queue size to the largest value and set maximum queue delay to be larger than the simulation time
894  Config::SetDefault ("ns3::WifiMacQueue::MaxDelay", TimeValue (Seconds (2 * duration)));
895 
896  CommandLine cmd (__FILE__);
897  cmd.AddValue ("verbose", "Logging level (0: no log - 1: simulation script logs - 2: all logs)", verbose);
898  cmd.AddValue ("tracing", "Generate trace files", tracing);
899  cmd.AddValue ("pktSize", "The packet size in bytes", pktSize);
900  cmd.AddValue ("trials", "The maximal number of runs per network size", trials);
901  cmd.AddValue ("duration", "Time duration for each trial in seconds", duration);
902  cmd.AddValue ("pcap", "Enable/disable PCAP tracing", pcap);
903  cmd.AddValue ("infra", "True to use infrastructure mode, false to use ring adhoc mode", infra);
904  cmd.AddValue ("workDir", "The working directory used to store generated files", workDir);
905  cmd.AddValue ("phyRate", "Set the constant PHY rate in Mbps used to transmit Data frames", phyRate);
906  cmd.AddValue ("standard", "Set the standard (11a, 11b, 11g, 11n, 11ac, 11ax)", standard);
907  cmd.AddValue ("nMinStas", "Minimum number of stations to start with", nMinStas);
908  cmd.AddValue ("nMaxStas", "Maximum number of stations to start with", nMaxStas);
909  cmd.AddValue ("nStepSize", "Number of stations to add at each step", nStepSize);
910  cmd.AddValue ("validate", "Enable/disable validation of the ns-3 simulations against the Bianchi model", validate);
911  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);
912  cmd.Parse (argc, argv);
913 
914  if (tracing)
915  {
916  cwTraceFile.open ("wifi-bianchi-cw-trace.out");
917  if (!cwTraceFile.is_open ())
918  {
919  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-cw-trace.out");
920  }
921  backoffTraceFile.open ("wifi-bianchi-backoff-trace.out");
922  if (!backoffTraceFile.is_open ())
923  {
924  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-backoff-trace.out");
925  }
926  phyTxTraceFile.open ("wifi-bianchi-phy-tx-trace.out");
927  if (!phyTxTraceFile.is_open ())
928  {
929  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-phy-tx-trace.out");
930  }
931  macTxTraceFile.open ("wifi-bianchi-mac-tx-trace.out");
932  if (!macTxTraceFile.is_open ())
933  {
934  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-mac-tx-trace.out");
935  }
936  macRxTraceFile.open ("wifi-bianchi-mac-rx-trace.out");
937  if (!macRxTraceFile.is_open ())
938  {
939  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-mac-rx-trace.out");
940  }
941  socketSendTraceFile.open ("wifi-bianchi-socket-send-trace.out");
942  if (!socketSendTraceFile.is_open ())
943  {
944  NS_FATAL_ERROR ("Failed to open file wifi-bianchi-socket-send-trace.out");
945  }
946  }
947 
948  if (verbose >= 1)
949  {
950  LogComponentEnable ("WifiBianchi", LOG_LEVEL_ALL);
951  }
952  if (verbose >= 2)
953  {
955  }
956 
957  std::stringstream ss;
958  ss << "wifi-"<< standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") << "-r-" << phyRate << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize << "-throughput.plt";
959  std::ofstream throughputPlot (ss.str ().c_str ());
960  ss.str ("");
961  ss << "wifi-" << standard << "-p-" << pktSize << (infra ? "-infrastructure" : "-adhoc") <<"-r-" << phyRate << "-min-" << nMinStas << "-max-" << nMaxStas << "-step-" << nStepSize << "-throughput.eps";
962  Gnuplot gnuplot = Gnuplot (ss.str ());
963 
964  WifiStandard wifiStandard;
965  std::stringstream phyRateStr;
966  if (standard == "11a")
967  {
968  wifiStandard = WIFI_STANDARD_80211a;
969  if ((phyRate != 6) && (phyRate != 9) && (phyRate != 12) && (phyRate != 18) && (phyRate != 24) && (phyRate != 36) && (phyRate != 48) && (phyRate != 54))
970  {
971  NS_FATAL_ERROR ("Selected PHY rate " << phyRate << " is not defined in " << standard);
972  }
973  phyRateStr << "OfdmRate" << phyRate << "Mbps";
974  }
975  else if (standard == "11b")
976  {
977  wifiStandard = WIFI_STANDARD_80211b;
978  if ((phyRate != 1) && (phyRate != 2) && (phyRate != 5.5) && (phyRate != 11))
979  {
980  NS_FATAL_ERROR ("Selected PHY rate " << phyRate << " is not defined in " << standard);
981  }
982  if (phyRate == 5.5)
983  {
984  phyRateStr << "DsssRate5_5Mbps";
985  }
986  else
987  {
988  phyRateStr << "DsssRate" << phyRate << "Mbps";
989  }
990  }
991  else if (standard == "11g")
992  {
993  wifiStandard = WIFI_STANDARD_80211g;
994  if ((phyRate != 6) && (phyRate != 9) && (phyRate != 12) && (phyRate != 18) && (phyRate != 24) && (phyRate != 36) && (phyRate != 48) && (phyRate != 54))
995  {
996  NS_FATAL_ERROR ("Selected PHY rate " << phyRate << " is not defined in " << standard);
997  }
998  phyRateStr << "ErpOfdmRate" << phyRate << "Mbps";
999  }
1000  else
1001  {
1002  NS_FATAL_ERROR ("Unsupported standard: " << standard);
1003  }
1004 
1005  YansWifiPhyHelper wifiPhy;
1006  YansWifiChannelHelper wifiChannel;
1007  wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
1008  wifiChannel.AddPropagationLoss ("ns3::LogDistancePropagationLossModel");
1009  wifiPhy.DisablePreambleDetectionModel ();
1010 
1011  WifiMacHelper wifiMac;
1012 
1013  WifiHelper wifi;
1014  wifi.SetStandard (wifiStandard);
1015  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue (phyRateStr.str()));
1016 
1017  Gnuplot2dDataset dataset;
1018  Gnuplot2dDataset datasetBianchiEifs;
1019  Gnuplot2dDataset datasetBianchiDifs;
1022  datasetBianchiEifs.SetStyle (Gnuplot2dDataset::LINES_POINTS);
1023  datasetBianchiDifs.SetStyle (Gnuplot2dDataset::LINES_POINTS);
1024 
1026  double averageThroughput, throughputArray[trials];
1027  for (uint32_t n = nMinStas; n <= nMaxStas; n += nStepSize)
1028  {
1029  averageThroughput = 0;
1030  double throughput;
1031  for (uint32_t runIndex = 0; runIndex < trials; runIndex++)
1032  {
1033  packetsReceived.clear ();
1034  bytesReceived.clear ();
1035  packetsTransmitted.clear ();
1036  psduFailed.clear ();
1037  psduSucceeded.clear ();
1038  phyHeaderFailed.clear ();
1039  timeFirstReceived.clear ();
1040  timeLastReceived.clear ();
1042  rxEventWhileRxing.clear ();
1043  rxEventWhileTxing.clear ();
1044  rxEventAbortedByTx.clear ();
1045  associated.clear ();
1046  throughput = 0;
1047  std::cout << "Trial " << runIndex + 1 << " of " << trials << "; "<< phyRate << " Mbps for " << n << " nodes " << std::endl;
1048  if (tracing)
1049  {
1050  cwTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "<< phyRate << " Mbps for " << n << " nodes" << std::endl;
1051  backoffTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; "<< phyRate << " Mbps for " << n << " nodes" << std::endl;
1052  phyTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1053  macTxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1054  macRxTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1055  socketSendTraceFile << "# Trial " << runIndex + 1 << " of " << trials << "; " << phyRate << " Mbps for " << n << " nodes" << std::endl;
1056  }
1057  experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, runIndex, n, duration, pcap, infra);
1058  uint32_t k = 0;
1059  if (bytesReceived.size () != n)
1060  {
1061  NS_FATAL_ERROR ("Not all stations got traffic!");
1062  }
1063  for (auto it = bytesReceived.begin (); it != bytesReceived.end (); it++, k++)
1064  {
1065  Time first = timeFirstReceived.find (it->first)->second;
1066  Time last = timeLastReceived.find (it->first)->second;
1067  Time dataTransferDuration = last - first;
1068  double nodeThroughput = (it->second * 8 / static_cast<double> (dataTransferDuration.GetMicroSeconds ()));
1069  throughput += nodeThroughput;
1070  uint64_t nodeTxPackets = GetCount (packetsTransmitted, it->first);
1071  uint64_t nodeRxPackets = GetCount (packetsReceived, it->first);
1072  uint64_t nodePhyHeaderFailures = GetCount (phyHeaderFailed, it->first);
1073  uint64_t nodePsduFailures = GetCount (psduFailed, it->first);
1074  uint64_t nodePsduSuccess = GetCount (psduSucceeded, it->first);
1075  uint64_t nodeRxEventWhileDecodingPreamble = GetCount (rxEventWhileDecodingPreamble, it->first);
1076  uint64_t nodeRxEventWhileRxing = GetCount (rxEventWhileRxing, it->first);
1077  uint64_t nodeRxEventWhileTxing = GetCount (rxEventWhileTxing, it->first);
1078  uint64_t nodeRxEventAbortedByTx = GetCount (rxEventAbortedByTx, it->first);
1079  uint64_t nodeRxEvents =
1080  nodePhyHeaderFailures + nodePsduFailures + nodePsduSuccess + nodeRxEventWhileDecodingPreamble +
1081  nodeRxEventWhileRxing + nodeRxEventWhileTxing + nodeRxEventAbortedByTx;
1082  std::cout << "Node " << it->first
1083  << ": TX packets " << nodeTxPackets
1084  << "; RX packets " << nodeRxPackets
1085  << "; PHY header failures " << nodePhyHeaderFailures
1086  << "; PSDU failures " << nodePsduFailures
1087  << "; PSDU success " << nodePsduSuccess
1088  << "; RX events while decoding preamble " << nodeRxEventWhileDecodingPreamble
1089  << "; RX events while RXing " << nodeRxEventWhileRxing
1090  << "; RX events while TXing " << nodeRxEventWhileTxing
1091  << "; RX events aborted by TX " << nodeRxEventAbortedByTx
1092  << "; total RX events " << nodeRxEvents
1093  << "; total events " << nodeTxPackets + nodeRxEvents
1094  << "; time first RX " << first
1095  << "; time last RX " << last
1096  << "; dataTransferDuration " << dataTransferDuration
1097  << "; throughput " << nodeThroughput << " Mbps" << std::endl;
1098  }
1099  std::cout << "Total throughput: " << throughput << " Mbps" << std::endl;
1100  averageThroughput += throughput;
1101  throughputArray[runIndex] = throughput;
1102  }
1103  averageThroughput = averageThroughput / trials;
1104 
1105  bool rateFound = false;
1106  double relativeErrorDifs = 0;
1107  double relativeErrorEifs = 0;
1108  auto itDifs = bianchiResultsDifs.find (static_cast<unsigned int> (phyRate * 1000000));
1109  if (itDifs != bianchiResultsDifs.end ())
1110  {
1111  rateFound = true;
1112  auto it = itDifs->second.find (n);
1113  if (it != itDifs->second.end ())
1114  {
1115  relativeErrorDifs = (std::abs (averageThroughput - it->second) / it->second);
1116  std::cout << "Relative error (DIFS): " << 100 * relativeErrorDifs << "%" << std::endl;
1117  }
1118  else if (validate)
1119  {
1120  NS_FATAL_ERROR ("No Bianchi results (DIFS) calculated for that number of stations!");
1121  }
1122  }
1123  auto itEifs = bianchiResultsEifs.find (static_cast<unsigned int> (phyRate * 1000000));
1124  if (itEifs != bianchiResultsEifs.end ())
1125  {
1126  rateFound = true;
1127  auto it = itEifs->second.find (n);
1128  if (it != itEifs->second.end ())
1129  {
1130  relativeErrorEifs = (std::abs (averageThroughput - it->second) / it->second);
1131  std::cout << "Relative error (EIFS): " << 100 * relativeErrorEifs << "%" << std::endl;
1132  }
1133  else if (validate)
1134  {
1135  NS_FATAL_ERROR ("No Bianchi results (EIFS) calculated for that number of stations!");
1136  }
1137  }
1138  if (!rateFound && validate)
1139  {
1140  NS_FATAL_ERROR ("No Bianchi results calculated for that rate!");
1141  }
1142  double relativeError = std::min (relativeErrorDifs, relativeErrorEifs);
1143  if (validate && (relativeError > maxRelativeError))
1144  {
1145  NS_FATAL_ERROR ("Relative error is too high!");
1146  }
1147 
1148  double stDev = 0;
1149  for (uint32_t i = 0; i < trials; ++i)
1150  {
1151  stDev += pow (throughputArray[i] - averageThroughput, 2);
1152  }
1153  stDev = sqrt (stDev / (trials - 1));
1154  dataset.Add (n, averageThroughput, stDev);
1155  }
1156  dataset.SetTitle ("ns-3");
1157 
1158  auto itDifs = bianchiResultsDifs.find (static_cast<unsigned int> (phyRate * 1000000));
1159  if (itDifs != bianchiResultsDifs.end ())
1160  {
1161  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1162  {
1163  double value = 0.0;
1164  auto it = itDifs->second.find (i);
1165  if (it != itDifs->second.end ())
1166  {
1167  value = it->second;
1168  }
1169  datasetBianchiDifs.Add (i, value);
1170  }
1171  }
1172  else
1173  {
1174  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1175  {
1176  datasetBianchiDifs.Add (i, 0.0);
1177  }
1178  }
1179 
1180  auto itEifs = bianchiResultsEifs.find (static_cast<unsigned int> (phyRate * 1000000));
1181  if (itEifs != bianchiResultsEifs.end ())
1182  {
1183  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1184  {
1185  double value = 0.0;
1186  auto it = itEifs->second.find (i);
1187  if (it != itEifs->second.end ())
1188  {
1189  value = it->second;
1190  }
1191  datasetBianchiEifs.Add (i, value);
1192  }
1193  }
1194  else
1195  {
1196  for (uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
1197  {
1198  datasetBianchiEifs.Add (i, 0.0);
1199  }
1200  }
1201 
1202  datasetBianchiEifs.SetTitle ("Bianchi (EIFS - lower bound)");
1203  datasetBianchiDifs.SetTitle ("Bianchi (DIFS - upper bound)");
1204  gnuplot.AddDataset (dataset);
1205  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
1206  gnuplot.SetLegend ("Number of competing stations", "Throughput (Mbps)");
1207  ss.str ("");
1208  ss << "Frame size " << pktSize << " bytes";
1209  gnuplot.SetTitle (ss.str ());
1210  ss.str ("");
1211  ss << "set xrange [" << nMinStas << ":" << nMaxStas << "]\n"
1212  << "set xtics " << nStepSize << "\n"
1213  << "set grid xtics ytics\n"
1214  << "set mytics\n"
1215  << "set style line 1 linewidth 5\n"
1216  << "set style line 2 linewidth 5\n"
1217  << "set style line 3 linewidth 5\n"
1218  << "set style line 4 linewidth 5\n"
1219  << "set style line 5 linewidth 5\n"
1220  << "set style line 6 linewidth 5\n"
1221  << "set style line 7 linewidth 5\n"
1222  << "set style line 8 linewidth 5\n"
1223  << "set style increment user";
1224  gnuplot.SetExtra (ss.str ());
1225  if (plotBianchiModel & 0x01)
1226  {
1227  datasetBianchiDifs.SetTitle ("Bianchi");
1228  gnuplot.AddDataset (datasetBianchiDifs);
1229  }
1230  if (plotBianchiModel & 0x02)
1231  {
1232  datasetBianchiEifs.SetTitle ("Bianchi");
1233  gnuplot.AddDataset (datasetBianchiEifs);
1234  }
1235  if (plotBianchiModel == 0x03)
1236  {
1237  datasetBianchiEifs.SetTitle ("Bianchi (EIFS - lower bound)");
1238  datasetBianchiDifs.SetTitle ("Bianchi (DIFS - upper bound)");
1239  }
1240  gnuplot.GenerateOutput (throughputPlot);
1241  throughputPlot.close ();
1242 
1243  if (tracing)
1244  {
1245  cwTraceFile.close ();
1246  backoffTraceFile.close ();
1247  phyTxTraceFile.close ();
1248  macTxTraceFile.close ();
1249  macRxTraceFile.close ();
1250  socketSendTraceFile.close ();
1251  }
1252 
1253  return 0;
1254 }
MpduInfo structure.
Definition: wifi-phy.h:126
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)
#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:99
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: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: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: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:978
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:119
#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
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: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: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
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.
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