satellite-stats-delay-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-geo-net-device.h>
42 #include <ns3/satellite-helper.h>
43 #include <ns3/satellite-id-mapper.h>
44 #include <ns3/satellite-mac.h>
45 #include <ns3/satellite-net-device.h>
46 #include <ns3/satellite-phy.h>
47 #include <ns3/satellite-time-tag.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 <sstream>
55 
56 NS_LOG_COMPONENT_DEFINE("SatStatsDelayHelper");
57 
58 namespace ns3
59 {
60 
61 NS_OBJECT_ENSURE_REGISTERED(SatStatsDelayHelper);
62 
63 SatStatsDelayHelper::SatStatsDelayHelper(Ptr<const SatHelper> satHelper)
64  : SatStatsHelper(satHelper),
65  m_averagingMode(false)
66 {
67  NS_LOG_FUNCTION(this << satHelper);
68 }
69 
71 {
72  NS_LOG_FUNCTION(this);
73 }
74 
75 TypeId // static
77 {
78  static TypeId tid =
79  TypeId("ns3::SatStatsDelayHelper")
80  .SetParent<SatStatsHelper>()
81  .AddAttribute("AveragingMode",
82  "If true, all samples will be averaged before passed to aggregator. "
83  "Only affects histogram, PDF, and CDF output types.",
84  BooleanValue(false),
85  MakeBooleanAccessor(&SatStatsDelayHelper::SetAveragingMode,
87  MakeBooleanChecker());
88  return tid;
89 }
90 
91 void
93 {
94  NS_LOG_FUNCTION(this << averagingMode);
95  m_averagingMode = averagingMode;
96 }
97 
98 bool
100 {
101  return m_averagingMode;
102 }
103 
104 void
106 {
107  NS_LOG_FUNCTION(this);
108 
109  switch (GetOutputType())
110  {
112  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
113  << " is not a valid output type for this statistics.");
114  break;
115 
117  // Setup aggregator.
118  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
119  "OutputFileName",
120  StringValue(GetOutputFileName()),
121  "MultiFileMode",
122  BooleanValue(false),
123  "EnableContextPrinting",
124  BooleanValue(true),
125  "GeneralHeading",
126  StringValue(GetIdentifierHeading("delay_sec")));
127 
128  // Setup collectors.
129  m_terminalCollectors.SetType("ns3::ScalarCollector");
130  m_terminalCollectors.SetAttribute("InputDataType",
131  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
132  m_terminalCollectors.SetAttribute(
133  "OutputType",
134  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
136  m_terminalCollectors.ConnectToAggregator("Output",
137  m_aggregator,
138  &MultiFileAggregator::Write1d);
139  break;
140  }
141 
143  // Setup aggregator.
144  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
145  "OutputFileName",
146  StringValue(GetOutputFileName()),
147  "GeneralHeading",
148  StringValue(GetTimeHeading("delay_sec")));
149 
150  // Setup collectors.
151  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
152  m_terminalCollectors.SetAttribute("ConversionType",
153  EnumValue(UnitConversionCollector::TRANSPARENT));
155  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
156  m_aggregator,
157  &MultiFileAggregator::Write2d);
158  break;
159  }
160 
164  if (m_averagingMode)
165  {
166  // Setup aggregator.
167  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
168  "OutputFileName",
169  StringValue(GetOutputFileName()),
170  "MultiFileMode",
171  BooleanValue(false),
172  "EnableContextPrinting",
173  BooleanValue(false),
174  "GeneralHeading",
175  StringValue(GetDistributionHeading("delay_sec")));
176  Ptr<MultiFileAggregator> fileAggregator =
177  m_aggregator->GetObject<MultiFileAggregator>();
178  NS_ASSERT(fileAggregator != nullptr);
179 
180  // Setup the final-level collector.
181  m_averagingCollector = CreateObject<DistributionCollector>();
182  DistributionCollector::OutputType_t outputType =
183  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
185  {
186  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
187  }
189  {
190  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
191  }
192  m_averagingCollector->SetOutputType(outputType);
193  m_averagingCollector->SetName("0");
194  m_averagingCollector->TraceConnect(
195  "Output",
196  "0",
197  MakeCallback(&MultiFileAggregator::Write2d, fileAggregator));
198  m_averagingCollector->TraceConnect(
199  "OutputString",
200  "0",
201  MakeCallback(&MultiFileAggregator::AddContextHeading, fileAggregator));
202  m_averagingCollector->TraceConnect(
203  "Warning",
204  "0",
205  MakeCallback(&MultiFileAggregator::EnableContextWarning, fileAggregator));
206 
207  // Setup collectors.
208  m_terminalCollectors.SetType("ns3::ScalarCollector");
209  m_terminalCollectors.SetAttribute("InputDataType",
210  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
211  m_terminalCollectors.SetAttribute(
212  "OutputType",
213  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
215  Callback<void, double> callback =
216  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
217  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
218  it != m_terminalCollectors.End();
219  ++it)
220  {
221  it->second->TraceConnectWithoutContext("Output", callback);
222  }
223  }
224  else
225  {
226  // Setup aggregator.
227  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
228  "OutputFileName",
229  StringValue(GetOutputFileName()),
230  "GeneralHeading",
231  StringValue(GetDistributionHeading("delay_sec")));
232 
233  // Setup collectors.
234  m_terminalCollectors.SetType("ns3::DistributionCollector");
235  DistributionCollector::OutputType_t outputType =
236  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
238  {
239  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
240  }
242  {
243  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
244  }
245  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
247  m_terminalCollectors.ConnectToAggregator("Output",
248  m_aggregator,
249  &MultiFileAggregator::Write2d);
250  m_terminalCollectors.ConnectToAggregator("OutputString",
251  m_aggregator,
252  &MultiFileAggregator::AddContextHeading);
253  m_terminalCollectors.ConnectToAggregator("Warning",
254  m_aggregator,
255  &MultiFileAggregator::EnableContextWarning);
256  }
257 
258  break;
259  }
260 
263  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
264  << " is not a valid output type for this statistics.");
265  break;
266 
268  // Setup aggregator.
269  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
270  "OutputPath",
271  StringValue(GetOutputPath()),
272  "OutputFileName",
273  StringValue(GetName()));
274  Ptr<MagisterGnuplotAggregator> plotAggregator =
275  m_aggregator->GetObject<MagisterGnuplotAggregator>();
276  NS_ASSERT(plotAggregator != nullptr);
277  // plot->SetTitle ("");
278  plotAggregator->SetLegend("Time (in seconds)", "Packet delay (in seconds)");
279  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
280 
281  // Setup collectors.
282  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
283  m_terminalCollectors.SetAttribute("ConversionType",
284  EnumValue(UnitConversionCollector::TRANSPARENT));
286  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
287  it != m_terminalCollectors.End();
288  ++it)
289  {
290  const std::string context = it->second->GetName();
291  plotAggregator->Add2dDataset(context, context);
292  }
293  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
294  m_aggregator,
295  &MagisterGnuplotAggregator::Write2d);
296  break;
297  }
298 
302  if (m_averagingMode)
303  {
304  // Setup aggregator.
305  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
306  "OutputPath",
307  StringValue(GetOutputPath()),
308  "OutputFileName",
309  StringValue(GetName()));
310  Ptr<MagisterGnuplotAggregator> plotAggregator =
311  m_aggregator->GetObject<MagisterGnuplotAggregator>();
312  NS_ASSERT(plotAggregator != nullptr);
313  // plot->SetTitle ("");
314  plotAggregator->SetLegend("Packet delay (in seconds)", "Frequency");
315  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
316  plotAggregator->Add2dDataset(GetName(), GetName());
318 
319  // Setup the final-level collector.
320  m_averagingCollector = CreateObject<DistributionCollector>();
321  DistributionCollector::OutputType_t outputType =
322  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
324  {
325  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
326  }
328  {
329  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
330  }
331  m_averagingCollector->SetOutputType(outputType);
332  m_averagingCollector->SetName("0");
333  m_averagingCollector->TraceConnect(
334  "Output",
335  GetName(),
336  MakeCallback(&MagisterGnuplotAggregator::Write2d, plotAggregator));
338 
339  // Setup collectors.
340  m_terminalCollectors.SetType("ns3::ScalarCollector");
341  m_terminalCollectors.SetAttribute("InputDataType",
342  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
343  m_terminalCollectors.SetAttribute(
344  "OutputType",
345  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
347  Callback<void, double> callback =
348  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
349  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
350  it != m_terminalCollectors.End();
351  ++it)
352  {
353  it->second->TraceConnectWithoutContext("Output", callback);
354  }
355  }
356  else
357  {
358  // Setup aggregator.
359  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
360  "OutputPath",
361  StringValue(GetOutputPath()),
362  "OutputFileName",
363  StringValue(GetName()));
364  Ptr<MagisterGnuplotAggregator> plotAggregator =
365  m_aggregator->GetObject<MagisterGnuplotAggregator>();
366  NS_ASSERT(plotAggregator != nullptr);
367  // plot->SetTitle ("");
368  plotAggregator->SetLegend("Packet delay (in seconds)", "Frequency");
369  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
370 
371  // Setup collectors.
372  m_terminalCollectors.SetType("ns3::DistributionCollector");
373  DistributionCollector::OutputType_t outputType =
374  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
376  {
377  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
378  }
380  {
381  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
382  }
383  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
385  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
386  it != m_terminalCollectors.End();
387  ++it)
388  {
389  const std::string context = it->second->GetName();
390  plotAggregator->Add2dDataset(context, context);
391  }
392  m_terminalCollectors.ConnectToAggregator("Output",
393  m_aggregator,
394  &MagisterGnuplotAggregator::Write2d);
395  }
396 
397  break;
398  }
399 
400  default:
401  NS_FATAL_ERROR("SatStatsDelayHelper - Invalid output type");
402  break;
403  }
404 
405  // Setup probes and connect them to the collectors.
406  InstallProbes();
407 
408 } // end of `void DoInstall ();`
409 
410 void
412 {
413  // The method below is supposed to be implemented by the child class.
414  DoInstallProbes();
415 }
416 
417 void
418 SatStatsDelayHelper::RxDelayCallback(const Time& delay, const Address& from)
419 {
420  // NS_LOG_FUNCTION (this << delay.GetSeconds () << from);
421 
422  if (from.IsInvalid())
423  {
424  NS_LOG_WARN(this << " discarding a packet delay of " << delay.GetSeconds()
425  << " from statistics collection because of"
426  << " invalid sender address");
427  }
428  else
429  {
430  // Determine the identifier associated with the sender address.
431  std::map<const Address, uint32_t>::const_iterator it = m_identifierMap.find(from);
432 
433  if (it != m_identifierMap.end())
434  {
435  PassSampleToCollector(delay, it->second);
436  }
437  else
438  {
439  NS_LOG_WARN(this << " discarding a packet delay of " << delay.GetSeconds()
440  << " from statistics collection because of"
441  << " unknown sender address " << from);
442  }
443  }
444 }
445 
446 void
448 {
449  NS_LOG_FUNCTION(this << utNode->GetId());
450 
451  const SatIdMapper* satIdMapper = Singleton<SatIdMapper>::Get();
452  const Address addr = satIdMapper->GetUtMacWithNode(utNode);
453 
454  if (addr.IsInvalid())
455  {
456  NS_LOG_WARN(this << " Node " << utNode->GetId() << " is not a valid UT");
457  }
458  else
459  {
460  const uint32_t identifier = GetIdentifierForUt(utNode);
461  m_identifierMap[addr] = identifier;
462  NS_LOG_INFO(this << " associated address " << addr << " with identifier " << identifier);
463  }
464 }
465 
466 bool
467 SatStatsDelayHelper::ConnectProbeToCollector(Ptr<Probe> probe, uint32_t identifier)
468 {
469  NS_LOG_FUNCTION(this << probe << probe->GetName() << identifier);
470 
471  bool ret = false;
472  switch (GetOutputType())
473  {
476  ret = m_terminalCollectors.ConnectWithProbe(probe,
477  "OutputSeconds",
478  identifier,
479  &ScalarCollector::TraceSinkDouble);
480  break;
481 
484  ret = m_terminalCollectors.ConnectWithProbe(probe,
485  "OutputSeconds",
486  identifier,
487  &UnitConversionCollector::TraceSinkDouble);
488  break;
489 
496  if (m_averagingMode)
497  {
498  ret = m_terminalCollectors.ConnectWithProbe(probe,
499  "OutputSeconds",
500  identifier,
501  &ScalarCollector::TraceSinkDouble);
502  }
503  else
504  {
505  ret = m_terminalCollectors.ConnectWithProbe(probe,
506  "OutputSeconds",
507  identifier,
508  &DistributionCollector::TraceSinkDouble);
509  }
510  break;
511 
512  default:
513  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
514  << " is not a valid output type for this statistics.");
515  break;
516  }
517 
518  if (ret)
519  {
520  NS_LOG_INFO(this << " created probe " << probe->GetName() << ", connected to collector "
521  << identifier);
522  }
523  else
524  {
525  NS_LOG_WARN(this << " unable to connect probe " << probe->GetName() << " to collector "
526  << identifier);
527  }
528 
529  return ret;
530 }
531 
532 void
533 SatStatsDelayHelper::PassSampleToCollector(const Time& delay, uint32_t identifier)
534 {
535  // NS_LOG_FUNCTION (this << delay.GetSeconds () << identifier);
536 
537  Ptr<DataCollectionObject> collector = m_terminalCollectors.Get(identifier);
538  NS_ASSERT_MSG(collector != nullptr, "Unable to find collector with identifier " << identifier);
539 
540  switch (GetOutputType())
541  {
544  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
545  NS_ASSERT(c != nullptr);
546  c->TraceSinkDouble(0.0, delay.GetSeconds());
547  break;
548  }
549 
552  Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
553  NS_ASSERT(c != nullptr);
554  c->TraceSinkDouble(0.0, delay.GetSeconds());
555  break;
556  }
557 
564  if (m_averagingMode)
565  {
566  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
567  NS_ASSERT(c != nullptr);
568  c->TraceSinkDouble(0.0, delay.GetSeconds());
569  }
570  else
571  {
572  Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
573  NS_ASSERT(c != nullptr);
574  c->TraceSinkDouble(0.0, delay.GetSeconds());
575  }
576  break;
577 
578  default:
579  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
580  << " is not a valid output type for this statistics.");
581  break;
582 
583  } // end of `switch (GetOutputType ())`
584 
585 } // end of `void PassSampleToCollector (Time, uint32_t)`
586 
587 // FORWARD LINK APPLICATION-LEVEL /////////////////////////////////////////////
588 
589 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdAppDelayHelper);
590 
592  : SatStatsDelayHelper(satHelper)
593 {
594  NS_LOG_FUNCTION(this << satHelper);
595 }
596 
598 {
599  NS_LOG_FUNCTION(this);
600 }
601 
602 TypeId // static
604 {
605  static TypeId tid = TypeId("ns3::SatStatsFwdAppDelayHelper").SetParent<SatStatsDelayHelper>();
606  return tid;
607 }
608 
609 void
611 {
612  NS_LOG_FUNCTION(this);
613  NodeContainer utUsers = GetSatHelper()->GetUtUsers();
614 
615  for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
616  {
617  const int32_t utUserId = GetUtUserId(*it);
618  NS_ASSERT_MSG(utUserId > 0, "Node " << (*it)->GetId() << " is not a valid UT user");
619  const uint32_t identifier = GetIdentifierForUtUser(*it);
620 
621  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
622  {
623  Ptr<Application> app = (*it)->GetApplication(i);
624  bool isConnected = false;
625 
626  /*
627  * Some applications support RxDelay trace sources, and some other
628  * applications support Rx trace sources. Below we support both ways.
629  */
630  if (app->GetInstanceTypeId().LookupTraceSourceByName("RxDelay") != nullptr)
631  {
632  NS_LOG_INFO(this << " attempt to connect using RxDelay");
633 
634  // Create the probe.
635  std::ostringstream probeName;
636  probeName << utUserId << "-" << i;
637  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
638  probe->SetName(probeName.str());
639 
640  // Connect the object to the probe.
641  if (probe->ConnectByObject("RxDelay", app))
642  {
643  isConnected = ConnectProbeToCollector(probe, identifier);
644  m_probes.push_back(probe->GetObject<Probe>());
645  }
646  }
647  else if (app->GetInstanceTypeId().LookupTraceSourceByName("Rx") != nullptr)
648  {
649  NS_LOG_INFO(this << " attempt to connect using Rx");
650  Callback<void, Ptr<const Packet>, const Address&> rxCallback =
651  MakeBoundCallback(&SatStatsFwdAppDelayHelper::RxCallback, this, identifier);
652  isConnected = app->TraceConnectWithoutContext("Rx", rxCallback);
653  }
654 
655  if (isConnected)
656  {
657  NS_LOG_INFO(this << " successfully connected"
658  << " with node ID " << (*it)->GetId() << " application #" << i);
659  }
660  else
661  {
662  /*
663  * We're being tolerant here by only logging a warning, because
664  * not every kind of Application is equipped with the expected
665  * RxDelay or Rx trace source.
666  */
667  NS_LOG_WARN(this << " unable to connect"
668  << " with node ID " << (*it)->GetId() << " application #" << i);
669  }
670 
671  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
672 
673  } // end of `for (it = utUsers.Begin(); it != utUsers.End (); ++it)`
674 
675  /*
676  * Some sender applications might need a special attribute to be enabled
677  * before delay statistics can be computed. We enable it here.
678  */
679  NodeContainer gwUsers = GetSatHelper()->GetGwUsers();
680  for (NodeContainer::Iterator it = gwUsers.Begin(); it != gwUsers.End(); ++it)
681  {
682  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
683  {
684  Ptr<Application> app = (*it)->GetApplication(i);
685 
686  if (!app->SetAttributeFailSafe("EnableStatisticsTags", BooleanValue(true)))
687  {
688  NS_LOG_WARN(this << " node ID " << (*it)->GetId() << " application #" << i
689  << " might not produce the required tags"
690  << " in the packets it transmits,"
691  << " thus preventing delay statistics"
692  << " from this application");
693  }
694 
695  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
696 
697  } // end of `for (it = gwUsers.Begin(); it != gwUsers.End (); ++it)`
698 
699 } // end of `void DoInstallProbes ();`
700 
701 void // static
702 SatStatsFwdAppDelayHelper::RxCallback(Ptr<SatStatsFwdAppDelayHelper> helper,
703  uint32_t identifier,
704  Ptr<const Packet> packet,
705  const Address& from)
706 {
707  NS_LOG_FUNCTION(helper << identifier << packet << packet->GetSize() << from);
708 
709  // bool isTagged = false;
710  // ByteTagIterator it = packet->GetByteTagIterator ();
711  //
712  // while (!isTagged && it.HasNext ())
713  // {
714  // ByteTagIterator::Item item = it.Next ();
715  //
716  // if (item.GetTypeId () == TrafficTimeTag::GetTypeId ())
717  // {
718  // NS_LOG_DEBUG ("Contains a TrafficTimeTag tag:"
719  // << " start=" << item.GetStart ()
720  // << " end=" << item.GetEnd ());
721  // TrafficTimeTag timeTag;
722  // item.GetTag (timeTag);
723  // const Time delay = Simulator::Now () - timeTag.GetSenderTimestamp ();
724  // helper->PassSampleToCollector (delay, identifier);
725  // isTagged = true; // this will exit the while loop.
726  // }
727  // }
728  //
729  // if (!isTagged)
730  // {
731  // NS_LOG_WARN ("Discarding a packet of " << packet->GetSize ()
732  // << " from statistics collection"
733  // << " because it does not contain any TrafficTimeTag");
734  // }
735 
736  TrafficTimeTag timeTag;
737  if (packet->PeekPacketTag(timeTag))
738  {
739  NS_LOG_DEBUG("Contains a TrafficTimeTag tag");
740  const Time delay = Simulator::Now() - timeTag.GetSenderTimestamp();
741  helper->PassSampleToCollector(delay, identifier);
742  }
743  else
744  {
745  NS_LOG_WARN("Discarding a packet of " << packet->GetSize() << " from statistics collection"
746  << " because it does not contain any TrafficTimeTag");
747  }
748 }
749 
750 // FORWARD LINK DEVICE-LEVEL //////////////////////////////////////////////////
751 
752 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdDevDelayHelper);
753 
755  : SatStatsDelayHelper(satHelper)
756 {
757  NS_LOG_FUNCTION(this << satHelper);
758 }
759 
761 {
762  NS_LOG_FUNCTION(this);
763 }
764 
765 TypeId // static
767 {
768  static TypeId tid = TypeId("ns3::SatStatsFwdDevDelayHelper").SetParent<SatStatsDelayHelper>();
769  return tid;
770 }
771 
772 void
774 {
775  NS_LOG_FUNCTION(this);
776  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
777 
778  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
779  {
780  const int32_t utId = GetUtId(*it);
781  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
782  const uint32_t identifier = GetIdentifierForUt(*it);
783 
784  // Create the probe.
785  std::ostringstream probeName;
786  probeName << utId;
787  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
788  probe->SetName(probeName.str());
789 
790  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
791 
792  // Connect the object to the probe.
793  if (probe->ConnectByObject("RxDelay", dev) && ConnectProbeToCollector(probe, identifier))
794  {
795  m_probes.push_back(probe->GetObject<Probe>());
796 
797  // Enable statistics-related tags and trace sources on the device.
798  dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
799  }
800  else
801  {
802  NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatNetDevice"
803  << " at node ID " << (*it)->GetId() << " device #2");
804  }
805 
806  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
807 
808  // Enable statistics-related tags on the transmitting device.
809  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
810  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
811  {
812  NetDeviceContainer devs = GetGwSatNetDevice(*it);
813 
814  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
815  {
816  NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
817  (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
818  }
819  }
820 
821 } // end of `void DoInstallProbes ();`
822 
823 // FORWARD LINK MAC-LEVEL /////////////////////////////////////////////////////
824 
825 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdMacDelayHelper);
826 
828  : SatStatsDelayHelper(satHelper)
829 {
830  NS_LOG_FUNCTION(this << satHelper);
831 }
832 
834 {
835  NS_LOG_FUNCTION(this);
836 }
837 
838 TypeId // static
840 {
841  static TypeId tid = TypeId("ns3::SatStatsFwdMacDelayHelper").SetParent<SatStatsDelayHelper>();
842  return tid;
843 }
844 
845 void
847 {
848  NS_LOG_FUNCTION(this);
849  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
850 
851  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
852  {
853  const int32_t utId = GetUtId(*it);
854  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
855  const uint32_t identifier = GetIdentifierForUt(*it);
856 
857  // Create the probe.
858  std::ostringstream probeName;
859  probeName << utId;
860  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
861  probe->SetName(probeName.str());
862 
863  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
864  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
865  NS_ASSERT(satDev != nullptr);
866  Ptr<SatMac> satMac = satDev->GetMac();
867  NS_ASSERT(satMac != nullptr);
868 
869  // Connect the object to the probe.
870  if (probe->ConnectByObject("RxDelay", satMac) && ConnectProbeToCollector(probe, identifier))
871  {
872  m_probes.push_back(probe->GetObject<Probe>());
873 
874  // Enable statistics-related tags and trace sources on the device.
875  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
876  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
877  }
878  else
879  {
880  NS_FATAL_ERROR("Error connecting to RxDelay trace source of satMac"
881  << " at node ID " << (*it)->GetId() << " device #2");
882  }
883 
884  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
885 
886  // Enable statistics-related tags on the transmitting device.
887  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
888  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
889  {
890  NetDeviceContainer devs = GetGwSatNetDevice(*it);
891 
892  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
893  {
894  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
895  NS_ASSERT(satDev != nullptr);
896  Ptr<SatMac> satMac = satDev->GetMac();
897  NS_ASSERT(satMac != nullptr);
898 
899  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
900  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
901  }
902  }
903 
904 } // end of `void DoInstallProbes ();`
905 
906 // FORWARD LINK PHY-LEVEL /////////////////////////////////////////////////////
907 
908 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdPhyDelayHelper);
909 
911  : SatStatsDelayHelper(satHelper)
912 {
913  NS_LOG_FUNCTION(this << satHelper);
914 }
915 
917 {
918  NS_LOG_FUNCTION(this);
919 }
920 
921 TypeId // static
923 {
924  static TypeId tid = TypeId("ns3::SatStatsFwdPhyDelayHelper").SetParent<SatStatsDelayHelper>();
925  return tid;
926 }
927 
928 void
930 {
931  NS_LOG_FUNCTION(this);
932 
933  NodeContainer sats = GetSatHelper()->GetBeamHelper()->GetGeoSatNodes();
934 
935  for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
936  {
937  Ptr<NetDevice> dev = GetSatSatGeoNetDevice(*it);
938  Ptr<SatGeoNetDevice> satGeoDev = dev->GetObject<SatGeoNetDevice>();
939  NS_ASSERT(satGeoDev != nullptr);
940  std::map<uint32_t, Ptr<SatPhy>> satGeoFeederPhys = satGeoDev->GetFeederPhy();
941  Ptr<SatPhy> satPhy;
942  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satGeoFeederPhys.begin();
943  it2 != satGeoFeederPhys.end();
944  ++it2)
945  {
946  satPhy = it2->second;
947  NS_ASSERT(satPhy != nullptr);
948  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
949  }
950  std::map<uint32_t, Ptr<SatPhy>> satGeoUserPhys = satGeoDev->GetUserPhy();
951  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satGeoUserPhys.begin();
952  it2 != satGeoUserPhys.end();
953  ++it2)
954  {
955  satPhy = it2->second;
956  NS_ASSERT(satPhy != nullptr);
957  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
958  }
959  } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
960 
961  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
962 
963  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
964  {
965  const int32_t utId = GetUtId(*it);
966  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
967  const uint32_t identifier = GetIdentifierForUt(*it);
968 
969  // Create the probe.
970  std::ostringstream probeName;
971  probeName << utId;
972  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
973  probe->SetName(probeName.str());
974 
975  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
976  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
977  NS_ASSERT(satDev != nullptr);
978  Ptr<SatPhy> satPhy = satDev->GetPhy();
979  NS_ASSERT(satPhy != nullptr);
980 
981  // Connect the object to the probe.
982  if (probe->ConnectByObject("RxDelay", satPhy) && ConnectProbeToCollector(probe, identifier))
983  {
984  m_probes.push_back(probe->GetObject<Probe>());
985 
986  // Enable statistics-related tags and trace sources on the device.
987  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
988  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
989  }
990  else
991  {
992  NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatPhy"
993  << " at node ID " << (*it)->GetId() << " device #2");
994  }
995 
996  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
997 
998  // Enable statistics-related tags on the transmitting device.
999  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
1000  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1001  {
1002  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1003 
1004  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1005  {
1006  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1007  NS_ASSERT(satDev != nullptr);
1008  Ptr<SatPhy> satPhy = satDev->GetPhy();
1009  NS_ASSERT(satPhy != nullptr);
1010 
1011  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1012  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1013  }
1014  }
1015 
1016 } // end of `void DoInstallProbes ();`
1017 
1018 // RETURN LINK APPLICATION-LEVEL //////////////////////////////////////////////
1019 
1020 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnAppDelayHelper);
1021 
1023  : SatStatsDelayHelper(satHelper)
1024 {
1025  NS_LOG_FUNCTION(this << satHelper);
1026 }
1027 
1029 {
1030  NS_LOG_FUNCTION(this);
1031 }
1032 
1033 TypeId // static
1035 {
1036  static TypeId tid = TypeId("ns3::SatStatsRtnAppDelayHelper").SetParent<SatStatsDelayHelper>();
1037  return tid;
1038 }
1039 
1040 void
1042 {
1043  NS_LOG_FUNCTION(this);
1044 
1045  NodeContainer utUsers = GetSatHelper()->GetUtUsers();
1046  for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
1047  {
1048  // Create a map of UT user addresses and identifiers.
1050 
1051  /*
1052  * Some sender applications might need a special attribute to be enabled
1053  * before delay statistics can be computed. We enable it here.
1054  */
1055  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1056  {
1057  Ptr<Application> app = (*it)->GetApplication(i);
1058 
1059  if (!app->SetAttributeFailSafe("EnableStatisticsTags", BooleanValue(true)))
1060  {
1061  NS_LOG_WARN(this << " node ID " << (*it)->GetId() << " application #" << i
1062  << " might not produce the required tags"
1063  << " in the transmitted packets,"
1064  << " thus preventing delay statistics"
1065  << " from this sender application");
1066  }
1067 
1068  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1069 
1070  } // end of `for (NodeContainer::Iterator it: utUsers)`
1071 
1072  // Connect to trace sources at GW user node's applications.
1073 
1074  NodeContainer gwUsers = GetSatHelper()->GetGwUsers();
1075  Callback<void, const Time&, const Address&> rxDelayCallback =
1076  MakeCallback(&SatStatsRtnAppDelayHelper::Ipv4Callback, this);
1077  Callback<void, Ptr<const Packet>, const Address&> rxCallback =
1078  MakeCallback(&SatStatsRtnAppDelayHelper::RxCallback, this);
1079 
1080  for (NodeContainer::Iterator it = gwUsers.Begin(); it != gwUsers.End(); ++it)
1081  {
1082  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1083  {
1084  Ptr<Application> app = (*it)->GetApplication(i);
1085  bool isConnected = false;
1086 
1087  /*
1088  * Some applications support RxDelay trace sources, and some other
1089  * applications support Rx trace sources. Below we support both ways.
1090  */
1091  if (app->GetInstanceTypeId().LookupTraceSourceByName("RxDelay") != nullptr)
1092  {
1093  isConnected = app->TraceConnectWithoutContext("RxDelay", rxDelayCallback);
1094  }
1095  else if (app->GetInstanceTypeId().LookupTraceSourceByName("Rx") != nullptr)
1096  {
1097  isConnected = app->TraceConnectWithoutContext("Rx", rxCallback);
1098  }
1099 
1100  if (isConnected)
1101  {
1102  NS_LOG_INFO(this << " successfully connected"
1103  << " with node ID " << (*it)->GetId() << " application #" << i);
1104  }
1105  else
1106  {
1107  /*
1108  * We're being tolerant here by only logging a warning, because
1109  * not every kind of Application is equipped with the expected
1110  * RxDelay or Rx trace source.
1111  */
1112  NS_LOG_WARN(this << " unable to connect"
1113  << " with node ID " << (*it)->GetId() << " application #" << i);
1114  }
1115 
1116  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1117 
1118  } // end of `for (NodeContainer::Iterator it: gwUsers)`
1119 
1120 } // end of `void DoInstallProbes ();`
1121 
1122 void
1123 SatStatsRtnAppDelayHelper::RxCallback(Ptr<const Packet> packet, const Address& from)
1124 {
1125  // NS_LOG_FUNCTION (this << packet << packet->GetSize () << from);
1126 
1127  // bool isTagged = false;
1128  // ByteTagIterator it = packet->GetByteTagIterator ();
1129  //
1130  // while (!isTagged && it.HasNext ())
1131  // {
1132  // ByteTagIterator::Item item = it.Next ();
1133  //
1134  // if (item.GetTypeId () == TrafficTimeTag::GetTypeId ())
1135  // {
1136  // NS_LOG_DEBUG ("Contains a TrafficTimeTag tag:"
1137  // << " start=" << item.GetStart ()
1138  // << " end=" << item.GetEnd ());
1139  // TrafficTimeTag timeTag;
1140  // item.GetTag (timeTag);
1141  // const Time delay = Simulator::Now () - timeTag.GetSenderTimestamp ();
1142  // helper->PassSampleToCollector (delay, identifier);
1143  // isTagged = true; // this will exit the while loop.
1144  // }
1145  // }
1146  //
1147  // if (!isTagged)
1148  // {
1149  // NS_LOG_WARN ("Discarding a packet of " << packet->GetSize ()
1150  // << " from statistics collection"
1151  // << " because it does not contain any TrafficTimeTag");
1152  // }
1153 
1154  TrafficTimeTag timeTag;
1155  if (packet->PeekPacketTag(timeTag))
1156  {
1157  NS_LOG_DEBUG(this << " contains a TrafficTimeTag tag");
1158  Ipv4Callback(Simulator::Now() - timeTag.GetSenderTimestamp(), from);
1159  }
1160  else
1161  {
1162  NS_LOG_WARN(this << " discarding a packet of " << packet->GetSize()
1163  << " from statistics collection"
1164  << " because it does not contain any TrafficTimeTag");
1165  }
1166 
1167 } // end of `void RxCallback (Ptr<const Packet>, const Address);`
1168 
1169 void
1170 SatStatsRtnAppDelayHelper::Ipv4Callback(const Time& delay, const Address& from)
1171 {
1172  // NS_LOG_FUNCTION (this << Time.GetSeconds () << from);
1173 
1174  if (InetSocketAddress::IsMatchingType(from))
1175  {
1176  // Determine the identifier associated with the sender address.
1177  const Address ipv4Addr = InetSocketAddress::ConvertFrom(from).GetIpv4();
1178  std::map<const Address, uint32_t>::const_iterator it1 = m_identifierMap.find(ipv4Addr);
1179 
1180  if (it1 == m_identifierMap.end())
1181  {
1182  NS_LOG_WARN(this << " discarding a packet delay of " << delay.GetSeconds()
1183  << " from statistics collection because of"
1184  << " unknown sender IPV4 address " << ipv4Addr);
1185  }
1186  else
1187  {
1188  PassSampleToCollector(delay, it1->second);
1189  }
1190  }
1191  else
1192  {
1193  NS_LOG_WARN(this << " discarding a packet delay of " << delay.GetSeconds()
1194  << " from statistics collection"
1195  << " because it comes from sender " << from
1196  << " without valid InetSocketAddress");
1197  }
1198 }
1199 
1200 void
1202 {
1203  NS_LOG_FUNCTION(this << utUserNode->GetId());
1204 
1205  Ptr<Ipv4> ipv4 = utUserNode->GetObject<Ipv4>();
1206 
1207  if (ipv4 == nullptr)
1208  {
1209  NS_LOG_INFO(this << " Node " << utUserNode->GetId() << " does not support IPv4 protocol");
1210  }
1211  else if (ipv4->GetNInterfaces() >= 2)
1212  {
1213  const uint32_t identifier = GetIdentifierForUtUser(utUserNode);
1214 
1215  /*
1216  * Assuming that #0 is for loopback interface and #1 is for subscriber
1217  * network interface.
1218  */
1219  for (uint32_t i = 0; i < ipv4->GetNAddresses(1); i++)
1220  {
1221  const Address addr = ipv4->GetAddress(1, i).GetLocal();
1222  m_identifierMap[addr] = identifier;
1223  NS_LOG_INFO(this << " associated address " << addr << " with identifier "
1224  << identifier);
1225  }
1226  }
1227  else
1228  {
1229  NS_LOG_WARN(this << " Node " << utUserNode->GetId() << " is not a valid UT user");
1230  }
1231 }
1232 
1233 // RETURN LINK DEVICE-LEVEL ///////////////////////////////////////////////////
1234 
1235 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnDevDelayHelper);
1236 
1238  : SatStatsDelayHelper(satHelper)
1239 {
1240  NS_LOG_FUNCTION(this << satHelper);
1241 }
1242 
1244 {
1245  NS_LOG_FUNCTION(this);
1246 }
1247 
1248 TypeId // static
1250 {
1251  static TypeId tid = TypeId("ns3::SatStatsRtnDevDelayHelper").SetParent<SatStatsDelayHelper>();
1252  return tid;
1253 }
1254 
1255 void
1257 {
1258  NS_LOG_FUNCTION(this);
1259 
1260  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
1261  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1262  {
1263  // Create a map of UT addresses and identifiers.
1265 
1266  // Enable statistics-related tags and trace sources on the device.
1267  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1268  dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1269  }
1270 
1271  // Connect to trace sources at GW nodes.
1272 
1273  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
1274  Callback<void, const Time&, const Address&> callback =
1275  MakeCallback(&SatStatsRtnDevDelayHelper::RxDelayCallback, this);
1276 
1277  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1278  {
1279  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1280 
1281  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1282  {
1283  NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
1284 
1285  if ((*itDev)->TraceConnectWithoutContext("RxDelay", callback))
1286  {
1287  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1288  << " device #" << (*itDev)->GetIfIndex());
1289 
1290  // Enable statistics-related tags and trace sources on the device.
1291  (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1292  }
1293  else
1294  {
1295  NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatNetDevice"
1296  << " at node ID " << (*it)->GetId() << " device #"
1297  << (*itDev)->GetIfIndex());
1298  }
1299 
1300  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1301 
1302  } // end of `for (NodeContainer::Iterator it = gws)`
1303 
1304 } // end of `void DoInstallProbes ();`
1305 
1306 // RETURN LINK MAC-LEVEL //////////////////////////////////////////////////////
1307 
1308 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnMacDelayHelper);
1309 
1311  : SatStatsDelayHelper(satHelper)
1312 {
1313  NS_LOG_FUNCTION(this << satHelper);
1314 }
1315 
1317 {
1318  NS_LOG_FUNCTION(this);
1319 }
1320 
1321 TypeId // static
1323 {
1324  static TypeId tid = TypeId("ns3::SatStatsRtnMacDelayHelper").SetParent<SatStatsDelayHelper>();
1325  return tid;
1326 }
1327 
1328 void
1330 {
1331  NS_LOG_FUNCTION(this);
1332 
1333  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
1334  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1335  {
1336  // Create a map of UT addresses and identifiers.
1338 
1339  // Enable statistics-related tags and trace sources on the device.
1340  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1341  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1342  NS_ASSERT(satDev != nullptr);
1343  Ptr<SatMac> satMac = satDev->GetMac();
1344  NS_ASSERT(satMac != nullptr);
1345  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1346  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1347  }
1348 
1349  // Connect to trace sources at GW nodes.
1350 
1351  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
1352  Callback<void, const Time&, const Address&> callback =
1353  MakeCallback(&SatStatsRtnMacDelayHelper::RxDelayCallback, this);
1354 
1355  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1356  {
1357  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1358 
1359  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1360  {
1361  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1362  NS_ASSERT(satDev != nullptr);
1363  Ptr<SatMac> satMac = satDev->GetMac();
1364  NS_ASSERT(satMac != nullptr);
1365 
1366  // Connect the object to the probe.
1367  if (satMac->TraceConnectWithoutContext("RxDelay", callback))
1368  {
1369  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1370  << " device #" << satDev->GetIfIndex());
1371 
1372  // Enable statistics-related tags and trace sources on the device.
1373  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1374  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1375  }
1376  else
1377  {
1378  NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatNetDevice"
1379  << " at node ID " << (*it)->GetId() << " device #"
1380  << satDev->GetIfIndex());
1381  }
1382 
1383  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1384 
1385  } // end of `for (NodeContainer::Iterator it = gws)`
1386 
1387 } // end of `void DoInstallProbes ();`
1388 
1389 // RETURN LINK PHY-LEVEL //////////////////////////////////////////////////////
1390 
1391 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnPhyDelayHelper);
1392 
1394  : SatStatsDelayHelper(satHelper)
1395 {
1396  NS_LOG_FUNCTION(this << satHelper);
1397 }
1398 
1400 {
1401  NS_LOG_FUNCTION(this);
1402 }
1403 
1404 TypeId // static
1406 {
1407  static TypeId tid = TypeId("ns3::SatStatsRtnPhyDelayHelper").SetParent<SatStatsDelayHelper>();
1408  return tid;
1409 }
1410 
1411 void
1413 {
1414  NS_LOG_FUNCTION(this);
1415 
1416  NodeContainer sats = GetSatHelper()->GetBeamHelper()->GetGeoSatNodes();
1417 
1418  for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
1419  {
1420  Ptr<SatPhy> satPhy;
1421  Ptr<NetDevice> dev = GetSatSatGeoNetDevice(*it);
1422  Ptr<SatGeoNetDevice> satGeoDev = dev->GetObject<SatGeoNetDevice>();
1423  NS_ASSERT(satGeoDev != nullptr);
1424  std::map<uint32_t, Ptr<SatPhy>> satGeoFeederPhys = satGeoDev->GetFeederPhy();
1425  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satGeoFeederPhys.begin();
1426  it2 != satGeoFeederPhys.end();
1427  ++it2)
1428  {
1429  satPhy = it2->second;
1430  NS_ASSERT(satPhy != nullptr);
1431  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1432  }
1433  std::map<uint32_t, Ptr<SatPhy>> satGeoUserPhys = satGeoDev->GetUserPhy();
1434  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satGeoUserPhys.begin();
1435  it2 != satGeoUserPhys.end();
1436  ++it2)
1437  {
1438  satPhy = it2->second;
1439  NS_ASSERT(satPhy != nullptr);
1440  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1441  }
1442  } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
1443 
1444  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
1445  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1446  {
1447  // Create a map of UT addresses and identifiers.
1449 
1450  // Enable statistics-related tags and trace sources on the device.
1451  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1452  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1453  NS_ASSERT(satDev != nullptr);
1454  Ptr<SatPhy> satPhy = satDev->GetPhy();
1455  NS_ASSERT(satPhy != nullptr);
1456  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1457  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1458  }
1459 
1460  // Connect to trace sources at GW nodes.
1461 
1462  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
1463  Callback<void, const Time&, const Address&> callback =
1464  MakeCallback(&SatStatsRtnPhyDelayHelper::RxDelayCallback, this);
1465 
1466  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1467  {
1468  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1469 
1470  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1471  {
1472  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1473  NS_ASSERT(satDev != nullptr);
1474  Ptr<SatPhy> satPhy = satDev->GetPhy();
1475  NS_ASSERT(satPhy != nullptr);
1476 
1477  // Connect the object to the probe.
1478  if (satPhy->TraceConnectWithoutContext("RxDelay", callback))
1479  {
1480  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1481  << " device #" << satDev->GetIfIndex());
1482 
1483  // Enable statistics-related tags and trace sources on the device.
1484  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1485  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1486  }
1487  else
1488  {
1489  NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatNetDevice"
1490  << " at node ID " << (*it)->GetId() << " device #"
1491  << satDev->GetIfIndex());
1492  }
1493 
1494  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1495 
1496  } // end of `for (NodeContainer::Iterator it = gws)`
1497 
1498 } // end of `void DoInstallProbes ();`
1499 
1500 } // end of namespace ns3
SatGeoNetDevice to be utilized in geostationary satellite.
Class for ID-mapper.
Address GetUtMacWithNode(Ptr< Node > utNode) const
SatNetDevice to be utilized in the UT and GW nodes.
Base class for delay statistics helpers.
CollectorMap m_terminalCollectors
Maintains a list of collectors created by this helper.
void InstallProbes()
Set up several probes or other means of listeners and connect them to the collectors.
void SetAveragingMode(bool averagingMode)
void DoInstall()
Install the probes, collectors, and aggregators necessary to produce the statistics output.
void RxDelayCallback(const Time &delay, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
virtual void DoInstallProbes()=0
void PassSampleToCollector(const Time &delay, uint32_t identifier)
Find a collector with the right identifier and pass a sample data to it.
Ptr< DataCollectionObject > m_aggregator
The aggregator created by this helper.
std::map< const Address, uint32_t > m_identifierMap
Map of address and the identifier associated with it (for return link).
static TypeId GetTypeId()
inherited from ObjectBase base class
void SaveAddressAndIdentifier(Ptr< Node > utNode)
Save the address and the proper identifier from the given UT node.
bool m_averagingMode
AveragingMode attribute.
Ptr< DistributionCollector > m_averagingCollector
The final collector utilized in averaged output (histogram, PDF, and CDF).
SatStatsDelayHelper(Ptr< const SatHelper > satHelper)
virtual ~SatStatsDelayHelper()
/ Destructor.
bool ConnectProbeToCollector(Ptr< Probe > probe, uint32_t identifier)
Connect the probe to the right collector.
Produce forward link application-level delay statistics from a satellite module simulation.
static TypeId GetTypeId()
inherited from ObjectBase base class
std::list< Ptr< Probe > > m_probes
Maintains a list of probes created by this helper.
static void RxCallback(Ptr< SatStatsFwdAppDelayHelper > helper, uint32_t identifier, Ptr< const Packet > packet, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
SatStatsFwdAppDelayHelper(Ptr< const SatHelper > satHelper)
virtual ~SatStatsFwdAppDelayHelper()
Destructor for SatStatsFwdAppDelayHelper.
Produce forward link device-level delay statistics from a satellite module simulation.
SatStatsFwdDevDelayHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
std::list< Ptr< Probe > > m_probes
Maintains a list of probes created by this helper.
Produce forward link MAC-level delay statistics from a satellite module simulation.
SatStatsFwdMacDelayHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
std::list< Ptr< Probe > > m_probes
Maintains a list of probes created by this helper.
Produce forward link PHY-level delay statistics from a satellite module simulation.
std::list< Ptr< Probe > > m_probes
Maintains a list of probes created by this helper.
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsFwdPhyDelayHelper(Ptr< const SatHelper > satHelper)
Parent abstract class of all satellite statistics helpers.
Ptr< const SatHelper > GetSatHelper() const
uint32_t GetIdentifierForUtUser(Ptr< Node > utUserNode) const
static NetDeviceContainer GetGwSatNetDevice(Ptr< Node > gwNode)
static std::string GetOutputTypeName(OutputType_t outputType)
static Ptr< NetDevice > GetSatSatGeoNetDevice(Ptr< Node > satNode)
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 GetUtId(Ptr< Node > utNode) const
uint32_t CreateCollectorPerIdentifier(CollectorMap &collectorMap) const
Create one collector instance for each identifier in the simulation.
static Ptr< NetDevice > GetUtSatNetDevice(Ptr< Node > utNode)
OutputType_t GetOutputType() const
uint32_t GetIdentifierForUt(Ptr< Node > utNode) const
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
Produce return link application-level delay statistics from a satellite module simulation.
static TypeId GetTypeId()
inherited from ObjectBase base class
void Ipv4Callback(const Time &delay, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
void RxCallback(Ptr< const Packet > packet, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
SatStatsRtnAppDelayHelper(Ptr< const SatHelper > satHelper)
void SaveIpv4AddressAndIdentifier(Ptr< Node > utUserNode)
Save the IPv4 address and the proper identifier from the given UT user node.
Produce return link device-level delay statistics from a satellite module simulation.
SatStatsRtnDevDelayHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
Produce return link MAC-level delay statistics from a satellite module simulation.
SatStatsRtnMacDelayHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
Produce return link PHY-level delay statistics from a satellite module simulation.
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsRtnPhyDelayHelper(Ptr< const SatHelper > satHelper)
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.