satellite-stats-plt-helper.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Magister Solutions
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: Budiarto Herman <budiarto.herman@magister.fi>
19  *
20  */
21 
23 
24 #include <ns3/application-delay-probe.h>
25 #include <ns3/application.h>
26 #include <ns3/boolean.h>
27 #include <ns3/callback.h>
28 #include <ns3/data-collection-object.h>
29 #include <ns3/distribution-collector.h>
30 #include <ns3/enum.h>
31 #include <ns3/inet-socket-address.h>
32 #include <ns3/ipv4.h>
33 #include <ns3/log.h>
34 #include <ns3/mac48-address.h>
35 #include <ns3/magister-gnuplot-aggregator.h>
36 #include <ns3/multi-file-aggregator.h>
37 #include <ns3/net-device.h>
38 #include <ns3/node-container.h>
39 #include <ns3/nstime.h>
40 #include <ns3/probe.h>
41 #include <ns3/satellite-helper.h>
42 #include <ns3/satellite-id-mapper.h>
43 #include <ns3/satellite-mac.h>
44 #include <ns3/satellite-net-device.h>
45 #include <ns3/satellite-phy.h>
46 #include <ns3/satellite-time-tag.h>
47 #include <ns3/satellite-topology.h>
48 #include <ns3/scalar-collector.h>
49 #include <ns3/singleton.h>
50 #include <ns3/string.h>
51 #include <ns3/traffic-time-tag.h>
52 #include <ns3/unit-conversion-collector.h>
53 
54 #include <map>
55 #include <sstream>
56 #include <string>
57 #include <utility>
58 
59 NS_LOG_COMPONENT_DEFINE("SatStatsPltHelper");
60 
61 namespace ns3
62 {
63 
64 NS_OBJECT_ENSURE_REGISTERED(SatStatsPltHelper);
65 
66 SatStatsPltHelper::SatStatsPltHelper(Ptr<const SatHelper> satHelper)
67  : SatStatsHelper(satHelper),
68  m_averagingMode(false)
69 {
70  NS_LOG_FUNCTION(this << satHelper);
71 }
72 
74 {
75  NS_LOG_FUNCTION(this);
76 }
77 
78 TypeId // static
80 {
81  static TypeId tid =
82  TypeId("ns3::SatStatsPltHelper")
83  .SetParent<SatStatsHelper>()
84  .AddAttribute("AveragingMode",
85  "If true, all samples will be averaged before passed to aggregator. "
86  "Only affects histogram, PDF, and CDF output types.",
87  BooleanValue(false),
88  MakeBooleanAccessor(&SatStatsPltHelper::SetAveragingMode,
90  MakeBooleanChecker());
91  return tid;
92 }
93 
94 void
96 {
97  NS_LOG_FUNCTION(this << averagingMode);
98  m_averagingMode = averagingMode;
99 }
100 
101 bool
103 {
104  return m_averagingMode;
105 }
106 
107 void
109 {
110  NS_LOG_FUNCTION(this);
111 
112  switch (GetOutputType())
113  {
115  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
116  << " is not a valid output type for this statistics.");
117  break;
118 
120  // Setup aggregator.
121  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
122  "OutputFileName",
123  StringValue(GetOutputFileName()),
124  "MultiFileMode",
125  BooleanValue(false),
126  "EnableContextPrinting",
127  BooleanValue(true),
128  "GeneralHeading",
129  StringValue(GetIdentifierHeading("plt_sec")));
130 
131  // Setup collectors.
132  m_terminalCollectors.SetType("ns3::ScalarCollector");
133  m_terminalCollectors.SetAttribute("InputDataType",
134  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
135  m_terminalCollectors.SetAttribute(
136  "OutputType",
137  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
139  m_terminalCollectors.ConnectToAggregator("Output",
140  m_aggregator,
141  &MultiFileAggregator::Write1d);
142  break;
143  }
144 
146  // Setup aggregator.
147  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
148  "OutputFileName",
149  StringValue(GetOutputFileName()),
150  "GeneralHeading",
151  StringValue(GetTimeHeading("plt_sec")));
152 
153  // Setup collectors.
154  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
155  m_terminalCollectors.SetAttribute("ConversionType",
156  EnumValue(UnitConversionCollector::TRANSPARENT));
158  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
159  m_aggregator,
160  &MultiFileAggregator::Write2d);
161  break;
162  }
163 
167  if (m_averagingMode)
168  {
169  // Setup aggregator.
170  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
171  "OutputFileName",
172  StringValue(GetOutputFileName()),
173  "MultiFileMode",
174  BooleanValue(false),
175  "EnableContextPrinting",
176  BooleanValue(false),
177  "GeneralHeading",
178  StringValue(GetDistributionHeading("plt_sec")));
179  Ptr<MultiFileAggregator> fileAggregator =
180  m_aggregator->GetObject<MultiFileAggregator>();
181  NS_ASSERT(fileAggregator != nullptr);
182 
183  // Setup the final-level collector.
184  m_averagingCollector = CreateObject<DistributionCollector>();
185  DistributionCollector::OutputType_t outputType =
186  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
188  {
189  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
190  }
192  {
193  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
194  }
195  m_averagingCollector->SetOutputType(outputType);
196  m_averagingCollector->SetName("0");
197  m_averagingCollector->TraceConnect(
198  "Output",
199  "0",
200  MakeCallback(&MultiFileAggregator::Write2d, fileAggregator));
201  m_averagingCollector->TraceConnect(
202  "OutputString",
203  "0",
204  MakeCallback(&MultiFileAggregator::AddContextHeading, fileAggregator));
205  m_averagingCollector->TraceConnect(
206  "Warning",
207  "0",
208  MakeCallback(&MultiFileAggregator::EnableContextWarning, fileAggregator));
209 
210  // Setup collectors.
211  m_terminalCollectors.SetType("ns3::ScalarCollector");
212  m_terminalCollectors.SetAttribute("InputDataType",
213  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
214  m_terminalCollectors.SetAttribute(
215  "OutputType",
216  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
218  Callback<void, double> callback =
219  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
220  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
221  it != m_terminalCollectors.End();
222  ++it)
223  {
224  it->second->TraceConnectWithoutContext("Output", callback);
225  }
226  }
227  else
228  {
229  // Setup aggregator.
230  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
231  "OutputFileName",
232  StringValue(GetOutputFileName()),
233  "GeneralHeading",
234  StringValue(GetDistributionHeading("plt_sec")));
235 
236  // Setup collectors.
237  m_terminalCollectors.SetType("ns3::DistributionCollector");
238  DistributionCollector::OutputType_t outputType =
239  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
241  {
242  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
243  }
245  {
246  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
247  }
248  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
250  m_terminalCollectors.ConnectToAggregator("Output",
251  m_aggregator,
252  &MultiFileAggregator::Write2d);
253  m_terminalCollectors.ConnectToAggregator("OutputString",
254  m_aggregator,
255  &MultiFileAggregator::AddContextHeading);
256  m_terminalCollectors.ConnectToAggregator("Warning",
257  m_aggregator,
258  &MultiFileAggregator::EnableContextWarning);
259  }
260 
261  break;
262  }
263 
266  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
267  << " is not a valid output type for this statistics.");
268  break;
269 
271  // Setup aggregator.
272  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
273  "OutputPath",
274  StringValue(GetOutputPath()),
275  "OutputFileName",
276  StringValue(GetName()));
277  Ptr<MagisterGnuplotAggregator> plotAggregator =
278  m_aggregator->GetObject<MagisterGnuplotAggregator>();
279  NS_ASSERT(plotAggregator != nullptr);
280  // plot->SetTitle ("");
281  plotAggregator->SetLegend("Time (in seconds)", "Object PLT (in seconds)");
282  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
283 
284  // Setup collectors.
285  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
286  m_terminalCollectors.SetAttribute("ConversionType",
287  EnumValue(UnitConversionCollector::TRANSPARENT));
289  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
290  it != m_terminalCollectors.End();
291  ++it)
292  {
293  const std::string context = it->second->GetName();
294  plotAggregator->Add2dDataset(context, context);
295  }
296  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
297  m_aggregator,
298  &MagisterGnuplotAggregator::Write2d);
299  break;
300  }
301 
305  if (m_averagingMode)
306  {
307  // Setup aggregator.
308  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
309  "OutputPath",
310  StringValue(GetOutputPath()),
311  "OutputFileName",
312  StringValue(GetName()));
313  Ptr<MagisterGnuplotAggregator> plotAggregator =
314  m_aggregator->GetObject<MagisterGnuplotAggregator>();
315  NS_ASSERT(plotAggregator != nullptr);
316  // plot->SetTitle ("");
317  plotAggregator->SetLegend("Object PLT (in seconds)", "Frequency");
318  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
319  plotAggregator->Add2dDataset(GetName(), GetName());
321 
322  // Setup the final-level collector.
323  m_averagingCollector = CreateObject<DistributionCollector>();
324  DistributionCollector::OutputType_t outputType =
325  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
327  {
328  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
329  }
331  {
332  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
333  }
334  m_averagingCollector->SetOutputType(outputType);
335  m_averagingCollector->SetName("0");
336  m_averagingCollector->TraceConnect(
337  "Output",
338  GetName(),
339  MakeCallback(&MagisterGnuplotAggregator::Write2d, plotAggregator));
341 
342  // Setup collectors.
343  m_terminalCollectors.SetType("ns3::ScalarCollector");
344  m_terminalCollectors.SetAttribute("InputDataType",
345  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
346  m_terminalCollectors.SetAttribute(
347  "OutputType",
348  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
350  Callback<void, double> callback =
351  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
352  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
353  it != m_terminalCollectors.End();
354  ++it)
355  {
356  it->second->TraceConnectWithoutContext("Output", callback);
357  }
358  }
359  else
360  {
361  // Setup aggregator.
362  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
363  "OutputPath",
364  StringValue(GetOutputPath()),
365  "OutputFileName",
366  StringValue(GetName()));
367  Ptr<MagisterGnuplotAggregator> plotAggregator =
368  m_aggregator->GetObject<MagisterGnuplotAggregator>();
369  NS_ASSERT(plotAggregator != nullptr);
370  // plot->SetTitle ("");
371  plotAggregator->SetLegend("Object PLT (in seconds)", "Frequency");
372  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
373 
374  // Setup collectors.
375  m_terminalCollectors.SetType("ns3::DistributionCollector");
376  DistributionCollector::OutputType_t outputType =
377  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
379  {
380  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
381  }
383  {
384  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
385  }
386  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
388  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
389  it != m_terminalCollectors.End();
390  ++it)
391  {
392  const std::string context = it->second->GetName();
393  plotAggregator->Add2dDataset(context, context);
394  }
395  m_terminalCollectors.ConnectToAggregator("Output",
396  m_aggregator,
397  &MagisterGnuplotAggregator::Write2d);
398  }
399 
400  break;
401  }
402 
403  default:
404  NS_FATAL_ERROR("SatStatsPltHelper - Invalid output type");
405  break;
406  }
407 
408  // Setup probes and connect them to the collectors.
409  InstallProbes();
410 
411 } // end of `void DoInstall ();`
412 
413 void
415 {
416  // The method below is supposed to be implemented by the child class.
417  DoInstallProbes();
418 }
419 
420 void
421 SatStatsPltHelper::RxPltCallback(const Time& plt, const Address& from)
422 {
423  // NS_LOG_FUNCTION (this << plt.GetSeconds () << from);
424 
425  if (from.IsInvalid())
426  {
427  NS_LOG_WARN(this << " discarding a object PLT of " << plt.GetSeconds()
428  << " from statistics collection because of"
429  << " invalid sender address");
430  }
431  else
432  {
433  // Determine the identifier associated with the sender address.
434  std::map<const Address, uint32_t>::const_iterator it = m_identifierMap.find(from);
435 
436  if (it != m_identifierMap.end())
437  {
438  PassSampleToCollector(plt, it->second);
439  }
440  else
441  {
442  NS_LOG_WARN(this << " discarding a object PLT of " << plt.GetSeconds()
443  << " from statistics collection because of"
444  << " unknown sender address " << from);
445  }
446  }
447 }
448 
449 bool
450 SatStatsPltHelper::ConnectProbeToCollector(Ptr<Probe> probe, uint32_t identifier)
451 {
452  NS_LOG_FUNCTION(this << probe << probe->GetName() << identifier);
453 
454  bool ret = false;
455  switch (GetOutputType())
456  {
459  ret = m_terminalCollectors.ConnectWithProbe(probe,
460  "OutputSeconds",
461  identifier,
462  &ScalarCollector::TraceSinkDouble);
463  break;
464 
467  ret = m_terminalCollectors.ConnectWithProbe(probe,
468  "OutputSeconds",
469  identifier,
470  &UnitConversionCollector::TraceSinkDouble);
471  break;
472 
479  if (m_averagingMode)
480  {
481  ret = m_terminalCollectors.ConnectWithProbe(probe,
482  "OutputSeconds",
483  identifier,
484  &ScalarCollector::TraceSinkDouble);
485  }
486  else
487  {
488  ret = m_terminalCollectors.ConnectWithProbe(probe,
489  "OutputSeconds",
490  identifier,
491  &DistributionCollector::TraceSinkDouble);
492  }
493  break;
494 
495  default:
496  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
497  << " is not a valid output type for this statistics.");
498  break;
499  }
500 
501  if (ret)
502  {
503  NS_LOG_INFO(this << " created probe " << probe->GetName() << ", connected to collector "
504  << identifier);
505  }
506  else
507  {
508  NS_LOG_WARN(this << " unable to connect probe " << probe->GetName() << " to collector "
509  << identifier);
510  }
511 
512  return ret;
513 }
514 
515 bool
516 SatStatsPltHelper::DisconnectProbeFromCollector(Ptr<Probe> probe, uint32_t identifier)
517 {
518  NS_LOG_FUNCTION(this << probe << probe->GetName() << identifier);
519 
520  bool ret = false;
521  switch (GetOutputType())
522  {
525  ret = m_terminalCollectors.DisconnectWithProbe(probe,
526  "OutputSeconds",
527  identifier,
528  &ScalarCollector::TraceSinkDouble);
529  break;
530 
533  ret = m_terminalCollectors.DisconnectWithProbe(probe,
534  "OutputSeconds",
535  identifier,
536  &UnitConversionCollector::TraceSinkDouble);
537  break;
538 
545  if (m_averagingMode)
546  {
547  ret = m_terminalCollectors.DisconnectWithProbe(probe,
548  "OutputSeconds",
549  identifier,
550  &ScalarCollector::TraceSinkDouble);
551  }
552  else
553  {
554  ret = m_terminalCollectors.DisconnectWithProbe(probe,
555  "OutputSeconds",
556  identifier,
557  &DistributionCollector::TraceSinkDouble);
558  }
559  break;
560 
561  default:
562  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
563  << " is not a valid output type for this statistics.");
564  break;
565  }
566 
567  if (ret)
568  {
569  NS_LOG_INFO(this << " probe " << probe->GetName() << ", disconnected from collector "
570  << identifier);
571  }
572  else
573  {
574  NS_LOG_WARN(this << " unable to disconnect probe " << probe->GetName() << " from collector "
575  << identifier);
576  }
577 
578  return ret;
579 }
580 
581 void
582 SatStatsPltHelper::PassSampleToCollector(const Time& plt, uint32_t identifier)
583 {
584  // NS_LOG_FUNCTION (this << plt.GetSeconds () << identifier);
585 
586  Ptr<DataCollectionObject> collector = m_terminalCollectors.Get(identifier);
587  NS_ASSERT_MSG(collector != nullptr, "Unable to find collector with identifier " << identifier);
588 
589  switch (GetOutputType())
590  {
593  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
594  NS_ASSERT(c != nullptr);
595  c->TraceSinkDouble(0.0, plt.GetSeconds());
596  break;
597  }
598 
601  Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
602  NS_ASSERT(c != nullptr);
603  c->TraceSinkDouble(0.0, plt.GetSeconds());
604  break;
605  }
606 
613  if (m_averagingMode)
614  {
615  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
616  NS_ASSERT(c != nullptr);
617  c->TraceSinkDouble(0.0, plt.GetSeconds());
618  }
619  else
620  {
621  Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
622  NS_ASSERT(c != nullptr);
623  c->TraceSinkDouble(0.0, plt.GetSeconds());
624  }
625  break;
626 
627  default:
628  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
629  << " is not a valid output type for this statistics.");
630  break;
631 
632  } // end of `switch (GetOutputType ())`
633 
634 } // end of `void PassSampleToCollector (Time, uint32_t)`
635 
636 // FORWARD LINK APPLICATION-LEVEL /////////////////////////////////////////////
637 
638 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdAppPltHelper);
639 
641  : SatStatsPltHelper(satHelper)
642 {
643  NS_LOG_FUNCTION(this << satHelper);
644 }
645 
647 {
648  NS_LOG_FUNCTION(this);
649 }
650 
651 TypeId // static
653 {
654  static TypeId tid = TypeId("ns3::SatStatsFwdAppPltHelper").SetParent<SatStatsPltHelper>();
655  return tid;
656 }
657 
658 void
660 {
661  NS_LOG_FUNCTION(this);
662  NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtUserNodes();
663 
664  for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
665  {
666  const int32_t utUserId = GetUtUserId(*it);
667  NS_ASSERT_MSG(utUserId > 0, "Node " << (*it)->GetId() << " is not a valid UT user");
668  const uint32_t identifier = GetIdentifierForUtUser(*it);
669 
670  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
671  {
672  Ptr<Application> app = (*it)->GetApplication(i);
673  bool isConnected = false;
674 
675  if (app->GetInstanceTypeId().LookupTraceSourceByName("RxPlt") != nullptr)
676  {
677  NS_LOG_INFO(this << " attempt to connect using RxPlt");
678 
679  // Create the probe.
680  std::ostringstream probeName;
681  probeName << utUserId << "-" << i;
682  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
683  probe->SetName(probeName.str());
684 
685  // Connect the object to the probe.
686  if (probe->ConnectByObject("RxPlt", app))
687  {
688  isConnected = ConnectProbeToCollector(probe, identifier);
689  m_probes.insert(
690  std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
691  }
692  }
693 
694  if (isConnected)
695  {
696  NS_LOG_INFO(this << " successfully connected"
697  << " with node ID " << (*it)->GetId() << " application #" << i);
698  }
699  else
700  {
701  /*
702  * We're being tolerant here by only logging a warning, because
703  * not every kind of Application is equipped with the expected
704  * RxPlt or Rx trace source.
705  */
706  NS_LOG_WARN(this << " unable to connect"
707  << " with node ID " << (*it)->GetId() << " application #" << i);
708  }
709 
710  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
711 
712  } // end of `for (it = utUsers.Begin(); it != utUsers.End (); ++it)`
713 
714 } // end of `void DoInstallProbes ();`
715 
716 void
718 {
719  NS_LOG_FUNCTION(this);
720 
721  std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
722 
723  for (it = m_probes.begin(); it != m_probes.end(); it++)
724  {
725  Ptr<Probe> probe = it->first;
726  Ptr<Node> node = it->second.first;
727  uint32_t identifier = it->second.second;
728 
729  if (!DisconnectProbeFromCollector(probe, identifier))
730  {
731  NS_FATAL_ERROR("Error disconnecting trace file on handover");
732  }
733 
734  identifier = GetIdentifierForUt(node);
735 
736  if (!ConnectProbeToCollector(probe, identifier))
737  {
738  NS_FATAL_ERROR("Error connecting trace file on handover");
739  }
740 
741  it->second.second = identifier;
742  }
743 } // end of `void UpdateIdentifierOnProbes ();`
744 
745 // RETURN LINK APPLICATION-LEVEL //////////////////////////////////////////////
746 
747 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnAppPltHelper);
748 
750  : SatStatsPltHelper(satHelper)
751 {
752  NS_LOG_FUNCTION(this << satHelper);
753 }
754 
756 {
757  NS_LOG_FUNCTION(this);
758 }
759 
760 TypeId // static
762 {
763  static TypeId tid = TypeId("ns3::SatStatsRtnAppPltHelper").SetParent<SatStatsPltHelper>();
764  return tid;
765 }
766 
767 void
769 {
770  NS_LOG_FUNCTION(this);
771 
772  // Connect to trace sources at GW user node's applications.
773  NodeContainer gwUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
774  Callback<void, const Time&, const Address&> rxPltCallback =
775  MakeCallback(&SatStatsRtnAppPltHelper::Ipv4Callback, this);
776 
777  for (NodeContainer::Iterator it = gwUsers.Begin(); it != gwUsers.End(); ++it)
778  {
779  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
780  {
781  Ptr<Application> app = (*it)->GetApplication(i);
782  bool isConnected = false;
783 
784  if (app->GetInstanceTypeId().LookupTraceSourceByName("RxPlt") != nullptr)
785  {
786  isConnected = app->TraceConnectWithoutContext("RxPlt", rxPltCallback);
787  }
788 
789  if (isConnected)
790  {
791  NS_LOG_INFO(this << " successfully connected"
792  << " with node ID " << (*it)->GetId() << " application #" << i);
793  }
794  else
795  {
796  /*
797  * We're being tolerant here by only logging a warning, because
798  * not every kind of Application is equipped with the expected
799  * RxPlt or Rx trace source.
800  */
801  NS_LOG_WARN(this << " unable to connect"
802  << " with node ID " << (*it)->GetId() << " application #" << i);
803  }
804 
805  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
806 
807  } // end of `for (NodeContainer::Iterator it: gwUsers)`
808 
809 } // end of `void DoInstallProbes ();`
810 
811 void
812 SatStatsRtnAppPltHelper::Ipv4Callback(const Time& plt, const Address& from)
813 {
814  // NS_LOG_FUNCTION (this << Time.GetSeconds () << from);
815 
816  if (InetSocketAddress::IsMatchingType(from))
817  {
818  // Determine the identifier associated with the sender address.
819  const Address ipv4Addr = InetSocketAddress::ConvertFrom(from).GetIpv4();
820  std::map<const Address, uint32_t>::const_iterator it1 = m_identifierMap.find(ipv4Addr);
821 
822  if (it1 == m_identifierMap.end())
823  {
824  NS_LOG_WARN(this << " discarding a object PLT of " << plt.GetSeconds()
825  << " from statistics collection because of"
826  << " unknown sender IPV4 address " << ipv4Addr);
827  }
828  else
829  {
830  PassSampleToCollector(plt, it1->second);
831  }
832  }
833  else
834  {
835  NS_LOG_WARN(this << " discarding a object PLT of " << plt.GetSeconds()
836  << " from statistics collection"
837  << " because it comes from sender " << from
838  << " without valid InetSocketAddress");
839  }
840 }
841 
842 void
844 {
845  NS_LOG_FUNCTION(this << utUserNode->GetId());
846 
847  Ptr<Ipv4> ipv4 = utUserNode->GetObject<Ipv4>();
848 
849  if (ipv4 == nullptr)
850  {
851  NS_LOG_INFO(this << " Node " << utUserNode->GetId() << " does not support IPv4 protocol");
852  }
853  else if (ipv4->GetNInterfaces() >= 2)
854  {
855  const uint32_t identifier = GetIdentifierForUtUser(utUserNode);
856 
857  /*
858  * Assuming that #0 is for loopback interface and #1 is for subscriber
859  * network interface.
860  */
861  for (uint32_t i = 0; i < ipv4->GetNAddresses(1); i++)
862  {
863  const Address addr = ipv4->GetAddress(1, i).GetLocal();
864  m_identifierMap[addr] = identifier;
865  NS_LOG_INFO(this << " associated address " << addr << " with identifier "
866  << identifier);
867  }
868  }
869  else
870  {
871  NS_LOG_WARN(this << " Node " << utUserNode->GetId() << " is not a valid UT user");
872  }
873 }
874 
875 } // end of namespace ns3
virtual ~SatStatsFwdAppPltHelper()
Destructor for SatStatsFwdAppPltHelper.
SatStatsFwdAppPltHelper(Ptr< const SatHelper > satHelper)
std::map< Ptr< Probe >, std::pair< Ptr< Node >, uint32_t > > m_probes
Maintains a list of probes created by this helper.
virtual void UpdateIdentifierOnProbes()
Change identifier used on probes, when handovers occur.
static TypeId GetTypeId()
inherited from ObjectBase base class
Parent abstract class of all satellite statistics helpers.
uint32_t GetIdentifierForUtUser(Ptr< Node > utUserNode) const
static std::string GetOutputTypeName(OutputType_t outputType)
virtual std::string GetIdentifierHeading(std::string dataLabel) const
virtual std::string GetOutputPath() const
Ptr< DataCollectionObject > CreateAggregator(std::string aggregatorTypeId, 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())
Create the aggregator according to the output type.
virtual std::string GetOutputFileName() const
Compute the path and file name where statistics output should be written to.
uint32_t CreateCollectorPerIdentifier(CollectorMap &collectorMap) const
Create one collector instance for each identifier in the simulation.
OutputType_t GetOutputType() const
uint32_t GetIdentifierForUt(Ptr< Node > utNode) const
std::map< const Address, uint32_t > m_identifierMap
Map of address and the identifier associated with it.
uint32_t GetUtUserId(Ptr< Node > utUserNode) const
std::string GetName() const
virtual std::string GetTimeHeading(std::string dataLabel) const
virtual std::string GetDistributionHeading(std::string dataLabel) const
Base class for PLT statistics helpers.
static TypeId GetTypeId()
inherited from ObjectBase base class
virtual void DoInstallProbes()=0
void RxPltCallback(const Time &plt, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
void DoInstall()
Install the probes, collectors, and aggregators necessary to produce the statistics output.
CollectorMap m_terminalCollectors
Maintains a list of collectors created by this helper.
Ptr< DistributionCollector > m_averagingCollector
The final collector utilized in averaged output (histogram, PDF, and CDF).
bool ConnectProbeToCollector(Ptr< Probe > probe, uint32_t identifier)
Connect the probe to the right collector.
bool m_averagingMode
AveragingMode attribute.
void SetAveragingMode(bool averagingMode)
bool DisconnectProbeFromCollector(Ptr< Probe > probe, uint32_t identifier)
Disconnect the probe from the right collector.
virtual ~SatStatsPltHelper()
/ Destructor.
SatStatsPltHelper(Ptr< const SatHelper > satHelper)
void InstallProbes()
Set up several probes or other means of listeners and connect them to the collectors.
Ptr< DataCollectionObject > m_aggregator
The aggregator created by this helper.
void PassSampleToCollector(const Time &plt, uint32_t identifier)
Find a collector with the right identifier and pass a sample data to it.
void Ipv4Callback(const Time &plt, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
virtual ~SatStatsRtnAppPltHelper()
/ Destructor.
void SaveIpv4AddressAndIdentifier(Ptr< Node > utUserNode)
Save the IPv4 address and the proper identifier from the given UT user node.
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsRtnAppPltHelper(Ptr< const SatHelper > satHelper)
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.