satellite-stats-jitter-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-orbiter-net-device.h>
46 #include <ns3/satellite-phy.h>
47 #include <ns3/satellite-time-tag.h>
48 #include <ns3/satellite-topology.h>
49 #include <ns3/scalar-collector.h>
50 #include <ns3/singleton.h>
51 #include <ns3/string.h>
52 #include <ns3/traffic-time-tag.h>
53 #include <ns3/unit-conversion-collector.h>
54 
55 #include <map>
56 #include <sstream>
57 #include <string>
58 #include <utility>
59 
60 NS_LOG_COMPONENT_DEFINE("SatStatsJitterHelper");
61 
62 namespace ns3
63 {
64 
65 NS_OBJECT_ENSURE_REGISTERED(SatStatsJitterHelper);
66 
67 SatStatsJitterHelper::SatStatsJitterHelper(Ptr<const SatHelper> satHelper)
68  : SatStatsHelper(satHelper),
69  m_averagingMode(false)
70 {
71  NS_LOG_FUNCTION(this << satHelper);
72 }
73 
75 {
76  NS_LOG_FUNCTION(this);
77 }
78 
79 TypeId // static
81 {
82  static TypeId tid =
83  TypeId("ns3::SatStatsJitterHelper")
84  .SetParent<SatStatsHelper>()
85  .AddAttribute("AveragingMode",
86  "If true, all samples will be averaged before passed to aggregator. "
87  "Only affects histogram, PDF, and CDF output types.",
88  BooleanValue(false),
89  MakeBooleanAccessor(&SatStatsJitterHelper::SetAveragingMode,
91  MakeBooleanChecker());
92  return tid;
93 }
94 
95 void
97 {
98  NS_LOG_FUNCTION(this << averagingMode);
99  m_averagingMode = averagingMode;
100 }
101 
102 bool
104 {
105  return m_averagingMode;
106 }
107 
108 void
110 {
111  NS_LOG_FUNCTION(this);
112 
113  switch (GetOutputType())
114  {
116  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
117  << " is not a valid output type for this statistics.");
118  break;
119 
121  // Setup aggregator.
122  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
123  "OutputFileName",
124  StringValue(GetOutputFileName()),
125  "MultiFileMode",
126  BooleanValue(false),
127  "EnableContextPrinting",
128  BooleanValue(true),
129  "GeneralHeading",
130  StringValue(GetIdentifierHeading("jitter_sec")));
131 
132  // Setup collectors.
133  m_terminalCollectors.SetType("ns3::ScalarCollector");
134  m_terminalCollectors.SetAttribute("InputDataType",
135  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
136  m_terminalCollectors.SetAttribute(
137  "OutputType",
138  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
140  m_terminalCollectors.ConnectToAggregator("Output",
141  m_aggregator,
142  &MultiFileAggregator::Write1d);
143  break;
144  }
145 
147  // Setup aggregator.
148  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
149  "OutputFileName",
150  StringValue(GetOutputFileName()),
151  "GeneralHeading",
152  StringValue(GetTimeHeading("jitter_sec")));
153 
154  // Setup collectors.
155  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
156  m_terminalCollectors.SetAttribute("ConversionType",
157  EnumValue(UnitConversionCollector::TRANSPARENT));
159  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
160  m_aggregator,
161  &MultiFileAggregator::Write2d);
162  break;
163  }
164 
168  if (m_averagingMode)
169  {
170  // Setup aggregator.
171  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
172  "OutputFileName",
173  StringValue(GetOutputFileName()),
174  "MultiFileMode",
175  BooleanValue(false),
176  "EnableContextPrinting",
177  BooleanValue(false),
178  "GeneralHeading",
179  StringValue(GetDistributionHeading("jitter_sec")));
180  Ptr<MultiFileAggregator> fileAggregator =
181  m_aggregator->GetObject<MultiFileAggregator>();
182  NS_ASSERT(fileAggregator != nullptr);
183 
184  // Setup the final-level collector.
185  m_averagingCollector = CreateObject<DistributionCollector>();
186  DistributionCollector::OutputType_t outputType =
187  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
189  {
190  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
191  }
193  {
194  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
195  }
196  m_averagingCollector->SetOutputType(outputType);
197  m_averagingCollector->SetName("0");
198  m_averagingCollector->TraceConnect(
199  "Output",
200  "0",
201  MakeCallback(&MultiFileAggregator::Write2d, fileAggregator));
202  m_averagingCollector->TraceConnect(
203  "OutputString",
204  "0",
205  MakeCallback(&MultiFileAggregator::AddContextHeading, fileAggregator));
206  m_averagingCollector->TraceConnect(
207  "Warning",
208  "0",
209  MakeCallback(&MultiFileAggregator::EnableContextWarning, fileAggregator));
210 
211  // Setup collectors.
212  m_terminalCollectors.SetType("ns3::ScalarCollector");
213  m_terminalCollectors.SetAttribute("InputDataType",
214  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
215  m_terminalCollectors.SetAttribute(
216  "OutputType",
217  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
219  Callback<void, double> callback =
220  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
221  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
222  it != m_terminalCollectors.End();
223  ++it)
224  {
225  it->second->TraceConnectWithoutContext("Output", callback);
226  }
227  }
228  else
229  {
230  // Setup aggregator.
231  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
232  "OutputFileName",
233  StringValue(GetOutputFileName()),
234  "GeneralHeading",
235  StringValue(GetDistributionHeading("jitter_sec")));
236 
237  // Setup collectors.
238  m_terminalCollectors.SetType("ns3::DistributionCollector");
239  DistributionCollector::OutputType_t outputType =
240  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
242  {
243  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
244  }
246  {
247  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
248  }
249  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
251  m_terminalCollectors.ConnectToAggregator("Output",
252  m_aggregator,
253  &MultiFileAggregator::Write2d);
254  m_terminalCollectors.ConnectToAggregator("OutputString",
255  m_aggregator,
256  &MultiFileAggregator::AddContextHeading);
257  m_terminalCollectors.ConnectToAggregator("Warning",
258  m_aggregator,
259  &MultiFileAggregator::EnableContextWarning);
260  }
261 
262  break;
263  }
264 
267  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
268  << " is not a valid output type for this statistics.");
269  break;
270 
272  // Setup aggregator.
273  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
274  "OutputPath",
275  StringValue(GetOutputPath()),
276  "OutputFileName",
277  StringValue(GetName()));
278  Ptr<MagisterGnuplotAggregator> plotAggregator =
279  m_aggregator->GetObject<MagisterGnuplotAggregator>();
280  NS_ASSERT(plotAggregator != nullptr);
281  // plot->SetTitle ("");
282  plotAggregator->SetLegend("Time (in seconds)", "Packet jitter (in seconds)");
283  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
284 
285  // Setup collectors.
286  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
287  m_terminalCollectors.SetAttribute("ConversionType",
288  EnumValue(UnitConversionCollector::TRANSPARENT));
290  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
291  it != m_terminalCollectors.End();
292  ++it)
293  {
294  const std::string context = it->second->GetName();
295  plotAggregator->Add2dDataset(context, context);
296  }
297  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
298  m_aggregator,
299  &MagisterGnuplotAggregator::Write2d);
300  break;
301  }
302 
306  if (m_averagingMode)
307  {
308  // Setup aggregator.
309  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
310  "OutputPath",
311  StringValue(GetOutputPath()),
312  "OutputFileName",
313  StringValue(GetName()));
314  Ptr<MagisterGnuplotAggregator> plotAggregator =
315  m_aggregator->GetObject<MagisterGnuplotAggregator>();
316  NS_ASSERT(plotAggregator != nullptr);
317  // plot->SetTitle ("");
318  plotAggregator->SetLegend("Packet jitter (in seconds)", "Frequency");
319  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
320  plotAggregator->Add2dDataset(GetName(), GetName());
322 
323  // Setup the final-level collector.
324  m_averagingCollector = CreateObject<DistributionCollector>();
325  DistributionCollector::OutputType_t outputType =
326  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
328  {
329  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
330  }
332  {
333  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
334  }
335  m_averagingCollector->SetOutputType(outputType);
336  m_averagingCollector->SetName("0");
337  m_averagingCollector->TraceConnect(
338  "Output",
339  GetName(),
340  MakeCallback(&MagisterGnuplotAggregator::Write2d, plotAggregator));
342 
343  // Setup collectors.
344  m_terminalCollectors.SetType("ns3::ScalarCollector");
345  m_terminalCollectors.SetAttribute("InputDataType",
346  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
347  m_terminalCollectors.SetAttribute(
348  "OutputType",
349  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
351  Callback<void, double> callback =
352  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
353  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
354  it != m_terminalCollectors.End();
355  ++it)
356  {
357  it->second->TraceConnectWithoutContext("Output", callback);
358  }
359  }
360  else
361  {
362  // Setup aggregator.
363  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
364  "OutputPath",
365  StringValue(GetOutputPath()),
366  "OutputFileName",
367  StringValue(GetName()));
368  Ptr<MagisterGnuplotAggregator> plotAggregator =
369  m_aggregator->GetObject<MagisterGnuplotAggregator>();
370  NS_ASSERT(plotAggregator != nullptr);
371  // plot->SetTitle ("");
372  plotAggregator->SetLegend("Packet jitter (in seconds)", "Frequency");
373  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
374 
375  // Setup collectors.
376  m_terminalCollectors.SetType("ns3::DistributionCollector");
377  DistributionCollector::OutputType_t outputType =
378  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
380  {
381  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
382  }
384  {
385  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
386  }
387  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
389  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
390  it != m_terminalCollectors.End();
391  ++it)
392  {
393  const std::string context = it->second->GetName();
394  plotAggregator->Add2dDataset(context, context);
395  }
396  m_terminalCollectors.ConnectToAggregator("Output",
397  m_aggregator,
398  &MagisterGnuplotAggregator::Write2d);
399  }
400 
401  break;
402  }
403 
404  default:
405  NS_FATAL_ERROR("SatStatsJitterHelper - Invalid output type");
406  break;
407  }
408 
409  // Setup probes and connect them to the collectors.
410  InstallProbes();
411 
412 } // end of `void DoInstall ();`
413 
414 void
416 {
417  // The method below is supposed to be implemented by the child class.
418  DoInstallProbes();
419 }
420 
421 void
422 SatStatsJitterHelper::RxJitterCallback(const Time& jitter, const Address& from)
423 {
424  // NS_LOG_FUNCTION (this << jitter.GetSeconds () << from);
425 
426  if (from.IsInvalid())
427  {
428  NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.GetSeconds()
429  << " from statistics collection because of"
430  << " invalid sender address");
431  }
432  else
433  {
434  // Determine the identifier associated with the sender address.
435  std::map<const Address, uint32_t>::const_iterator it = m_identifierMap.find(from);
436 
437  if (it != m_identifierMap.end())
438  {
439  PassSampleToCollector(jitter, it->second);
440  }
441  else
442  {
443  NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.GetSeconds()
444  << " from statistics collection because of"
445  << " unknown sender address " << from);
446  }
447  }
448 }
449 
450 bool
451 SatStatsJitterHelper::ConnectProbeToCollector(Ptr<Probe> probe, uint32_t identifier)
452 {
453  NS_LOG_FUNCTION(this << probe << probe->GetName() << identifier);
454 
455  bool ret = false;
456  switch (GetOutputType())
457  {
460  ret = m_terminalCollectors.ConnectWithProbe(probe,
461  "OutputSeconds",
462  identifier,
463  &ScalarCollector::TraceSinkDouble);
464  break;
465 
468  ret = m_terminalCollectors.ConnectWithProbe(probe,
469  "OutputSeconds",
470  identifier,
471  &UnitConversionCollector::TraceSinkDouble);
472  break;
473 
480  if (m_averagingMode)
481  {
482  ret = m_terminalCollectors.ConnectWithProbe(probe,
483  "OutputSeconds",
484  identifier,
485  &ScalarCollector::TraceSinkDouble);
486  }
487  else
488  {
489  ret = m_terminalCollectors.ConnectWithProbe(probe,
490  "OutputSeconds",
491  identifier,
492  &DistributionCollector::TraceSinkDouble);
493  }
494  break;
495 
496  default:
497  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
498  << " is not a valid output type for this statistics.");
499  break;
500  }
501 
502  if (ret)
503  {
504  NS_LOG_INFO(this << " created probe " << probe->GetName() << ", connected to collector "
505  << identifier);
506  }
507  else
508  {
509  NS_LOG_WARN(this << " unable to connect probe " << probe->GetName() << " to collector "
510  << identifier);
511  }
512 
513  return ret;
514 }
515 
516 bool
517 SatStatsJitterHelper::DisconnectProbeFromCollector(Ptr<Probe> probe, uint32_t identifier)
518 {
519  NS_LOG_FUNCTION(this << probe << probe->GetName() << identifier);
520 
521  bool ret = false;
522  switch (GetOutputType())
523  {
526  ret = m_terminalCollectors.DisconnectWithProbe(probe,
527  "OutputSeconds",
528  identifier,
529  &ScalarCollector::TraceSinkDouble);
530  break;
531 
534  ret = m_terminalCollectors.DisconnectWithProbe(probe,
535  "OutputSeconds",
536  identifier,
537  &UnitConversionCollector::TraceSinkDouble);
538  break;
539 
546  if (m_averagingMode)
547  {
548  ret = m_terminalCollectors.DisconnectWithProbe(probe,
549  "OutputSeconds",
550  identifier,
551  &ScalarCollector::TraceSinkDouble);
552  }
553  else
554  {
555  ret = m_terminalCollectors.DisconnectWithProbe(probe,
556  "OutputSeconds",
557  identifier,
558  &DistributionCollector::TraceSinkDouble);
559  }
560  break;
561 
562  default:
563  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
564  << " is not a valid output type for this statistics.");
565  break;
566  }
567 
568  if (ret)
569  {
570  NS_LOG_INFO(this << " probe " << probe->GetName() << ", disconnected from collector "
571  << identifier);
572  }
573  else
574  {
575  NS_LOG_WARN(this << " unable to disconnect probe " << probe->GetName() << " from collector "
576  << identifier);
577  }
578 
579  return ret;
580 }
581 
582 void
583 SatStatsJitterHelper::PassSampleToCollector(const Time& jitter, uint32_t identifier)
584 {
585  // NS_LOG_FUNCTION (this << jitter.GetSeconds () << identifier);
586 
587  Ptr<DataCollectionObject> collector = m_terminalCollectors.Get(identifier);
588  NS_ASSERT_MSG(collector != nullptr, "Unable to find collector with identifier " << identifier);
589 
590  switch (GetOutputType())
591  {
594  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
595  NS_ASSERT(c != nullptr);
596  c->TraceSinkDouble(0.0, jitter.GetSeconds());
597  break;
598  }
599 
602  Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
603  NS_ASSERT(c != nullptr);
604  c->TraceSinkDouble(0.0, jitter.GetSeconds());
605  break;
606  }
607 
614  if (m_averagingMode)
615  {
616  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
617  NS_ASSERT(c != nullptr);
618  c->TraceSinkDouble(0.0, jitter.GetSeconds());
619  }
620  else
621  {
622  Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
623  NS_ASSERT(c != nullptr);
624  c->TraceSinkDouble(0.0, jitter.GetSeconds());
625  }
626  break;
627 
628  default:
629  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
630  << " is not a valid output type for this statistics.");
631  break;
632 
633  } // end of `switch (GetOutputType ())`
634 
635 } // end of `void PassSampleToCollector (Time, uint32_t)`
636 
637 // FORWARD LINK APPLICATION-LEVEL /////////////////////////////////////////////
638 
639 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdAppJitterHelper);
640 
642  : SatStatsJitterHelper(satHelper)
643 {
644  NS_LOG_FUNCTION(this << satHelper);
645 }
646 
648 {
649  NS_LOG_FUNCTION(this);
650 }
651 
652 TypeId // static
654 {
655  static TypeId tid = TypeId("ns3::SatStatsFwdAppJitterHelper").SetParent<SatStatsJitterHelper>();
656  return tid;
657 }
658 
659 void
661 {
662  NS_LOG_FUNCTION(this);
663  NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtUserNodes();
664 
665  for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
666  {
667  const int32_t utUserId = GetUtUserId(*it);
668  NS_ASSERT_MSG(utUserId > 0, "Node " << (*it)->GetId() << " is not a valid UT user");
669  const uint32_t identifier = GetIdentifierForUtUser(*it);
670 
671  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
672  {
673  Ptr<Application> app = (*it)->GetApplication(i);
674  bool isConnected = false;
675 
676  /*
677  * Some applications support RxJitter trace sources, and some other
678  * applications support Rx trace sources. Below we support both ways.
679  */
680  if (app->GetInstanceTypeId().LookupTraceSourceByName("RxJitter") != nullptr)
681  {
682  NS_LOG_INFO(this << " attempt to connect using RxJitter");
683 
684  // Create the probe.
685  std::ostringstream probeName;
686  probeName << utUserId << "-" << i;
687  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
688  probe->SetName(probeName.str());
689 
690  // Connect the object to the probe.
691  if (probe->ConnectByObject("RxJitter", app))
692  {
693  isConnected = ConnectProbeToCollector(probe, identifier);
694  m_probes.insert(
695  std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
696  }
697  }
698  else if (app->GetInstanceTypeId().LookupTraceSourceByName("Rx") != nullptr)
699  {
700  NS_LOG_INFO(this << " attempt to connect using Rx");
701  Callback<void, Ptr<const Packet>, const Address&> rxCallback =
702  MakeBoundCallback(&SatStatsFwdAppJitterHelper::RxCallback, this, identifier);
703  isConnected = app->TraceConnectWithoutContext("Rx", rxCallback);
704  }
705 
706  if (isConnected)
707  {
708  NS_LOG_INFO(this << " successfully connected"
709  << " with node ID " << (*it)->GetId() << " application #" << i);
710  }
711  else
712  {
713  /*
714  * We're being tolerant here by only logging a warning, because
715  * not every kind of Application is equipped with the expected
716  * RxJitter or Rx trace source.
717  */
718  NS_LOG_WARN(this << " unable to connect"
719  << " with node ID " << (*it)->GetId() << " application #" << i);
720  }
721 
722  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
723 
724  } // end of `for (it = utUsers.Begin(); it != utUsers.End (); ++it)`
725 
726  /*
727  * Some sender applications might need a special attribute to be enabled
728  * before jitter statistics can be computed. We enable it here.
729  */
730  NodeContainer gwUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
731  for (NodeContainer::Iterator it = gwUsers.Begin(); it != gwUsers.End(); ++it)
732  {
733  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
734  {
735  Ptr<Application> app = (*it)->GetApplication(i);
736 
737  if (!app->SetAttributeFailSafe("EnableStatisticsTags", BooleanValue(true)))
738  {
739  NS_LOG_WARN(this << " node ID " << (*it)->GetId() << " application #" << i
740  << " might not produce the required tags"
741  << " in the packets it transmits,"
742  << " thus preventing jitter statistics"
743  << " from this application");
744  }
745 
746  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
747 
748  } // end of `for (it = gwUsers.Begin(); it != gwUsers.End (); ++it)`
749 
750 } // end of `void DoInstallProbes ();`
751 
752 void
754 {
755  NS_LOG_FUNCTION(this);
756 
757  std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
758 
759  for (it = m_probes.begin(); it != m_probes.end(); it++)
760  {
761  Ptr<Probe> probe = it->first;
762  Ptr<Node> node = it->second.first;
763  uint32_t identifier = it->second.second;
764 
765  if (!DisconnectProbeFromCollector(probe, identifier))
766  {
767  NS_FATAL_ERROR("Error disconnecting trace file on handover");
768  }
769 
770  identifier = GetIdentifierForUtUser(node);
771 
772  if (!ConnectProbeToCollector(probe, identifier))
773  {
774  NS_FATAL_ERROR("Error connecting trace file on handover");
775  }
776 
777  it->second.second = identifier;
778  }
779 } // end of `void UpdateIdentifierOnProbes ();`
780 
781 Time
782 SatStatsFwdAppJitterHelper::GetAndUpdatePreviousDelay(uint32_t identifier, Time newDelay)
783 {
784  NS_LOG_FUNCTION(identifier);
785 
786  Time delay = Seconds(0);
787  std::map<uint32_t, Time>::iterator it = m_previousDelayMap.find(identifier);
788  if (it != m_previousDelayMap.end())
789  {
790  delay = it->second;
791  }
792  m_previousDelayMap[identifier] = newDelay;
793  return delay;
794 }
795 
796 void // static
797 SatStatsFwdAppJitterHelper::RxCallback(Ptr<SatStatsFwdAppJitterHelper> helper,
798  uint32_t identifier,
799  Ptr<const Packet> packet,
800  const Address& from)
801 {
802  NS_LOG_FUNCTION(helper << identifier << packet << packet->GetSize() << from);
803 
804  TrafficTimeTag timeTag;
805  if (packet->PeekPacketTag(timeTag))
806  {
807  NS_LOG_DEBUG("Contains a TrafficTimeTag tag");
808  const Time delay = Simulator::Now() - timeTag.GetSenderTimestamp();
809  Time previousDelay = helper->GetAndUpdatePreviousDelay(identifier, delay);
810  if (previousDelay.IsZero() == false)
811  {
812  Time jitter = Abs(delay - previousDelay);
813  helper->PassSampleToCollector(jitter, identifier);
814  }
815  }
816  else
817  {
818  NS_LOG_WARN("Discarding a packet of " << packet->GetSize() << " from statistics collection"
819  << " because it does not contain any TrafficTimeTag");
820  }
821 }
822 
823 // FORWARD LINK DEVICE-LEVEL //////////////////////////////////////////////////
824 
825 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdDevJitterHelper);
826 
828  : SatStatsJitterHelper(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::SatStatsFwdDevJitterHelper").SetParent<SatStatsJitterHelper>();
842  return tid;
843 }
844 
845 void
847 {
848  NS_LOG_FUNCTION(this);
849  NodeContainer uts = Singleton<SatTopology>::Get()->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 
865  // Connect the object to the probe.
866  if (probe->ConnectByObject("RxJitter", dev) && ConnectProbeToCollector(probe, identifier))
867  {
868  m_probes.insert(
869  std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
870 
871  // Enable statistics-related tags and trace sources on the device.
872  dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
873  }
874  else
875  {
876  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
877  << " at node ID " << (*it)->GetId() << " device #2");
878  }
879 
880  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
881 
882  // Enable statistics-related tags on the transmitting device.
883  NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
884  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
885  {
886  NetDeviceContainer devs = GetGwSatNetDevice(*it);
887 
888  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
889  {
890  NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
891  (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
892  }
893  }
894 
895 } // end of `void DoInstallProbes ();`
896 
897 void
899 {
900  NS_LOG_FUNCTION(this);
901 
902  std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
903 
904  for (it = m_probes.begin(); it != m_probes.end(); it++)
905  {
906  Ptr<Probe> probe = it->first;
907  Ptr<Node> node = it->second.first;
908  uint32_t identifier = it->second.second;
909 
910  if (!DisconnectProbeFromCollector(probe, identifier))
911  {
912  NS_FATAL_ERROR("Error disconnecting trace file on handover");
913  }
914 
915  identifier = GetIdentifierForUtUser(node);
916 
917  if (!ConnectProbeToCollector(probe, identifier))
918  {
919  NS_FATAL_ERROR("Error connecting trace file on handover");
920  }
921 
922  it->second.second = identifier;
923  }
924 } // end of `void UpdateIdentifierOnProbes ();`
925 
926 // FORWARD LINK MAC-LEVEL /////////////////////////////////////////////////////
927 
928 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdMacJitterHelper);
929 
931  : SatStatsJitterHelper(satHelper)
932 {
933  NS_LOG_FUNCTION(this << satHelper);
934 }
935 
937 {
938  NS_LOG_FUNCTION(this);
939 }
940 
941 TypeId // static
943 {
944  static TypeId tid = TypeId("ns3::SatStatsFwdMacJitterHelper").SetParent<SatStatsJitterHelper>();
945  return tid;
946 }
947 
948 void
950 {
951  NS_LOG_FUNCTION(this);
952  NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
953 
954  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
955  {
956  const int32_t utId = GetUtId(*it);
957  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
958  const uint32_t identifier = GetIdentifierForUt(*it);
959 
960  // Create the probe.
961  std::ostringstream probeName;
962  probeName << utId;
963  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
964  probe->SetName(probeName.str());
965 
966  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
967  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
968  NS_ASSERT(satDev != nullptr);
969  Ptr<SatMac> satMac = satDev->GetMac();
970  NS_ASSERT(satMac != nullptr);
971 
972  // Connect the object to the probe.
973  if (probe->ConnectByObject("RxJitter", satMac) &&
974  ConnectProbeToCollector(probe, identifier))
975  {
976  m_probes.insert(
977  std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
978 
979  // Enable statistics-related tags and trace sources on the device.
980  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
981  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
982  }
983  else
984  {
985  NS_FATAL_ERROR("Error connecting to RxJitter trace source of satMac"
986  << " at node ID " << (*it)->GetId() << " device #2");
987  }
988 
989  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
990 
991  // Enable statistics-related tags on the transmitting device.
992  NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
993  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
994  {
995  NetDeviceContainer devs = GetGwSatNetDevice(*it);
996 
997  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
998  {
999  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1000  NS_ASSERT(satDev != nullptr);
1001  Ptr<SatMac> satMac = satDev->GetMac();
1002  NS_ASSERT(satMac != nullptr);
1003 
1004  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1005  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1006  }
1007  }
1008 
1009 } // end of `void DoInstallProbes ();`
1010 
1011 void
1013 {
1014  NS_LOG_FUNCTION(this);
1015 
1016  std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
1017 
1018  for (it = m_probes.begin(); it != m_probes.end(); it++)
1019  {
1020  Ptr<Probe> probe = it->first;
1021  Ptr<Node> node = it->second.first;
1022  uint32_t identifier = it->second.second;
1023 
1024  if (!DisconnectProbeFromCollector(probe, identifier))
1025  {
1026  NS_FATAL_ERROR("Error disconnecting trace file on handover");
1027  }
1028 
1029  identifier = GetIdentifierForUtUser(node);
1030 
1031  if (!ConnectProbeToCollector(probe, identifier))
1032  {
1033  NS_FATAL_ERROR("Error connecting trace file on handover");
1034  }
1035 
1036  it->second.second = identifier;
1037  }
1038 } // end of `void UpdateIdentifierOnProbes ();`
1039 
1040 // FORWARD LINK PHY-LEVEL /////////////////////////////////////////////////////
1041 
1042 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdPhyJitterHelper);
1043 
1045  : SatStatsJitterHelper(satHelper)
1046 {
1047  NS_LOG_FUNCTION(this << satHelper);
1048 }
1049 
1051 {
1052  NS_LOG_FUNCTION(this);
1053 }
1054 
1055 TypeId // static
1057 {
1058  static TypeId tid = TypeId("ns3::SatStatsFwdPhyJitterHelper").SetParent<SatStatsJitterHelper>();
1059  return tid;
1060 }
1061 
1062 void
1064 {
1065  NS_LOG_FUNCTION(this);
1066 
1067  NodeContainer sats = Singleton<SatTopology>::Get()->GetOrbiterNodes();
1068 
1069  for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
1070  {
1071  Ptr<NetDevice> dev = GetSatSatOrbiterNetDevice(*it);
1072  Ptr<SatOrbiterNetDevice> satOrbiterDev = dev->GetObject<SatOrbiterNetDevice>();
1073  NS_ASSERT(satOrbiterDev != nullptr);
1074  std::map<uint32_t, Ptr<SatPhy>> satOrbiterFeederPhys = satOrbiterDev->GetFeederPhy();
1075  Ptr<SatPhy> satPhy;
1076  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterFeederPhys.begin();
1077  it2 != satOrbiterFeederPhys.end();
1078  ++it2)
1079  {
1080  satPhy = it2->second;
1081  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1082  }
1083  std::map<uint32_t, Ptr<SatPhy>> satOrbiterUserPhys = satOrbiterDev->GetUserPhy();
1084  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterUserPhys.begin();
1085  it2 != satOrbiterUserPhys.end();
1086  ++it2)
1087  {
1088  satPhy = it2->second;
1089  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1090  }
1091  } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
1092 
1093  NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1094 
1095  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1096  {
1097  const int32_t utId = GetUtId(*it);
1098  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
1099  const uint32_t identifier = GetIdentifierForUt(*it);
1100 
1101  // Create the probe.
1102  std::ostringstream probeName;
1103  probeName << utId;
1104  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
1105  probe->SetName(probeName.str());
1106 
1107  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1108  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1109  NS_ASSERT(satDev != nullptr);
1110  Ptr<SatPhy> satPhy = satDev->GetPhy();
1111  NS_ASSERT(satPhy != nullptr);
1112 
1113  // Connect the object to the probe.
1114  if (probe->ConnectByObject("RxJitter", satPhy) &&
1115  ConnectProbeToCollector(probe, identifier))
1116  {
1117  m_probes.insert(
1118  std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
1119 
1120  // Enable statistics-related tags and trace sources on the device.
1121  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1122  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1123  }
1124  else
1125  {
1126  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatPhy"
1127  << " at node ID " << (*it)->GetId() << " device #2");
1128  }
1129 
1130  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
1131 
1132  // Enable statistics-related tags on the transmitting device.
1133  NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1134  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1135  {
1136  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1137 
1138  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1139  {
1140  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1141  NS_ASSERT(satDev != nullptr);
1142  Ptr<SatPhy> satPhy = satDev->GetPhy();
1143  NS_ASSERT(satPhy != nullptr);
1144 
1145  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1146  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1147  }
1148  }
1149 
1150 } // end of `void DoInstallProbes ();`
1151 
1152 void
1154 {
1155  NS_LOG_FUNCTION(this);
1156 
1157  std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
1158 
1159  for (it = m_probes.begin(); it != m_probes.end(); it++)
1160  {
1161  Ptr<Probe> probe = it->first;
1162  Ptr<Node> node = it->second.first;
1163  uint32_t identifier = it->second.second;
1164 
1165  if (!DisconnectProbeFromCollector(probe, identifier))
1166  {
1167  NS_FATAL_ERROR("Error disconnecting trace file on handover");
1168  }
1169 
1170  identifier = GetIdentifierForUtUser(node);
1171 
1172  if (!ConnectProbeToCollector(probe, identifier))
1173  {
1174  NS_FATAL_ERROR("Error connecting trace file on handover");
1175  }
1176 
1177  it->second.second = identifier;
1178  }
1179 } // end of `void UpdateIdentifierOnProbes ();`
1180 
1181 // RETURN LINK APPLICATION-LEVEL //////////////////////////////////////////////
1182 
1183 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnAppJitterHelper);
1184 
1186  : SatStatsJitterHelper(satHelper)
1187 {
1188  NS_LOG_FUNCTION(this << satHelper);
1189 }
1190 
1192 {
1193  NS_LOG_FUNCTION(this);
1194 }
1195 
1196 TypeId // static
1198 {
1199  static TypeId tid = TypeId("ns3::SatStatsRtnAppJitterHelper").SetParent<SatStatsJitterHelper>();
1200  return tid;
1201 }
1202 
1203 void
1205 {
1206  NS_LOG_FUNCTION(this);
1207 
1208  NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtUserNodes();
1209  for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
1210  {
1211  // Create a map of UT user addresses and identifiers.
1213 
1214  /*
1215  * Some sender applications might need a special attribute to be enabled
1216  * before jitter statistics can be computed. We enable it here.
1217  */
1218  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1219  {
1220  Ptr<Application> app = (*it)->GetApplication(i);
1221 
1222  if (!app->SetAttributeFailSafe("EnableStatisticsTags", BooleanValue(true)))
1223  {
1224  NS_LOG_WARN(this << " node ID " << (*it)->GetId() << " application #" << i
1225  << " might not produce the required tags"
1226  << " in the transmitted packets,"
1227  << " thus preventing jitter statistics"
1228  << " from this sender application");
1229  }
1230 
1231  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1232 
1233  } // end of `for (NodeContainer::Iterator it: utUsers)`
1234 
1235  // Connect to trace sources at GW user node's applications.
1236 
1237  NodeContainer gwUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
1238  Callback<void, const Time&, const Address&> rxJitterCallback =
1239  MakeCallback(&SatStatsRtnAppJitterHelper::Ipv4Callback, this);
1240  Callback<void, Ptr<const Packet>, const Address&> rxCallback =
1241  MakeCallback(&SatStatsRtnAppJitterHelper::RxCallback, this);
1242 
1243  for (NodeContainer::Iterator it = gwUsers.Begin(); it != gwUsers.End(); ++it)
1244  {
1245  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1246  {
1247  Ptr<Application> app = (*it)->GetApplication(i);
1248  bool isConnected = false;
1249 
1250  /*
1251  * Some applications support RxJitter trace sources, and some other
1252  * applications support Rx trace sources. Below we support both ways.
1253  */
1254  if (app->GetInstanceTypeId().LookupTraceSourceByName("RxJitter") != nullptr)
1255  {
1256  isConnected = app->TraceConnectWithoutContext("RxJitter", rxJitterCallback);
1257  }
1258  else if (app->GetInstanceTypeId().LookupTraceSourceByName("Rx") != nullptr)
1259  {
1260  isConnected = app->TraceConnectWithoutContext("Rx", rxCallback);
1261  }
1262 
1263  if (isConnected)
1264  {
1265  NS_LOG_INFO(this << " successfully connected"
1266  << " with node ID " << (*it)->GetId() << " application #" << i);
1267  }
1268  else
1269  {
1270  /*
1271  * We're being tolerant here by only logging a warning, because
1272  * not every kind of Application is equipped with the expected
1273  * RxJitter or Rx trace source.
1274  */
1275  NS_LOG_WARN(this << " unable to connect"
1276  << " with node ID " << (*it)->GetId() << " application #" << i);
1277  }
1278 
1279  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1280 
1281  } // end of `for (NodeContainer::Iterator it: gwUsers)`
1282 
1283 } // end of `void DoInstallProbes ();`
1284 
1285 void
1286 SatStatsRtnAppJitterHelper::RxCallback(Ptr<const Packet> packet, const Address& from)
1287 {
1288  TrafficTimeTag timeTag;
1289  if (packet->PeekPacketTag(timeTag))
1290  {
1291  NS_LOG_DEBUG(this << " contains a TrafficTimeTag tag");
1292  const Time delay = Simulator::Now() - timeTag.GetSenderTimestamp();
1293  const Address identifier = InetSocketAddress::ConvertFrom(from).GetIpv4();
1294  std::map<const Address, Time>::iterator it = m_previousDelayMap.find(identifier);
1295  if (it != m_previousDelayMap.end())
1296  {
1297  Time previousDelay = it->second;
1298  Time jitter = Abs(delay - previousDelay);
1299  Ipv4Callback(jitter, from);
1300  }
1301  m_previousDelayMap[identifier] = delay;
1302  }
1303  else
1304  {
1305  NS_LOG_WARN(this << " discarding a packet of " << packet->GetSize()
1306  << " from statistics collection"
1307  << " because it does not contain any TrafficTimeTag");
1308  }
1309 } // end of `void RxCallback (Ptr<const Packet>, const Address);`
1310 
1311 void
1312 SatStatsRtnAppJitterHelper::Ipv4Callback(const Time& jitter, const Address& from)
1313 {
1314  // NS_LOG_FUNCTION (this << Time.GetSeconds () << from);
1315 
1316  if (InetSocketAddress::IsMatchingType(from))
1317  {
1318  // Determine the identifier associated with the sender address.
1319  const Address ipv4Addr = InetSocketAddress::ConvertFrom(from).GetIpv4();
1320  std::map<const Address, uint32_t>::const_iterator it1 = m_identifierMap.find(ipv4Addr);
1321 
1322  if (it1 == m_identifierMap.end())
1323  {
1324  NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.GetSeconds()
1325  << " from statistics collection because of"
1326  << " unknown sender IPV4 address " << ipv4Addr);
1327  }
1328  else
1329  {
1330  PassSampleToCollector(jitter, it1->second);
1331  }
1332  }
1333  else
1334  {
1335  NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.GetSeconds()
1336  << " from statistics collection"
1337  << " because it comes from sender " << from
1338  << " without valid InetSocketAddress");
1339  }
1340 }
1341 
1342 void
1344 {
1345  NS_LOG_FUNCTION(this << utUserNode->GetId());
1346 
1347  Ptr<Ipv4> ipv4 = utUserNode->GetObject<Ipv4>();
1348 
1349  if (ipv4 == nullptr)
1350  {
1351  NS_LOG_INFO(this << " Node " << utUserNode->GetId() << " does not support IPv4 protocol");
1352  }
1353  else if (ipv4->GetNInterfaces() >= 2)
1354  {
1355  const uint32_t identifier = GetIdentifierForUtUser(utUserNode);
1356 
1357  /*
1358  * Assuming that #0 is for loopback interface and #1 is for subscriber
1359  * network interface.
1360  */
1361  for (uint32_t i = 0; i < ipv4->GetNAddresses(1); i++)
1362  {
1363  const Address addr = ipv4->GetAddress(1, i).GetLocal();
1364  m_identifierMap[addr] = identifier;
1365  NS_LOG_INFO(this << " associated address " << addr << " with identifier "
1366  << identifier);
1367  }
1368  }
1369  else
1370  {
1371  NS_LOG_WARN(this << " Node " << utUserNode->GetId() << " is not a valid UT user");
1372  }
1373 }
1374 
1375 // RETURN LINK DEVICE-LEVEL ///////////////////////////////////////////////////
1376 
1377 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnDevJitterHelper);
1378 
1380  : SatStatsJitterHelper(satHelper)
1381 {
1382  NS_LOG_FUNCTION(this << satHelper);
1383 }
1384 
1386 {
1387  NS_LOG_FUNCTION(this);
1388 }
1389 
1390 TypeId // static
1392 {
1393  static TypeId tid = TypeId("ns3::SatStatsRtnDevJitterHelper").SetParent<SatStatsJitterHelper>();
1394  return tid;
1395 }
1396 
1397 void
1399 {
1400  NS_LOG_FUNCTION(this);
1401 
1402  NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1403  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1404  {
1405  // Create a map of UT addresses and identifiers.
1407 
1408  // Enable statistics-related tags and trace sources on the device.
1409  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1410  dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1411  }
1412 
1413  // Connect to trace sources at GW nodes.
1414 
1415  NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1416  Callback<void, const Time&, const Address&> callback =
1417  MakeCallback(&SatStatsRtnDevJitterHelper::RxJitterCallback, this);
1418 
1419  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1420  {
1421  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1422 
1423  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1424  {
1425  NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
1426 
1427  if ((*itDev)->TraceConnectWithoutContext("RxJitter", callback))
1428  {
1429  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1430  << " device #" << (*itDev)->GetIfIndex());
1431 
1432  // Enable statistics-related tags and trace sources on the device.
1433  (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1434  }
1435  else
1436  {
1437  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
1438  << " at node ID " << (*it)->GetId() << " device #"
1439  << (*itDev)->GetIfIndex());
1440  }
1441 
1442  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1443 
1444  } // end of `for (NodeContainer::Iterator it = gws)`
1445 
1446 } // end of `void DoInstallProbes ();`
1447 
1448 // RETURN LINK MAC-LEVEL //////////////////////////////////////////////////////
1449 
1450 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnMacJitterHelper);
1451 
1453  : SatStatsJitterHelper(satHelper)
1454 {
1455  NS_LOG_FUNCTION(this << satHelper);
1456 }
1457 
1459 {
1460  NS_LOG_FUNCTION(this);
1461 }
1462 
1463 TypeId // static
1465 {
1466  static TypeId tid = TypeId("ns3::SatStatsRtnMacJitterHelper").SetParent<SatStatsJitterHelper>();
1467  return tid;
1468 }
1469 
1470 void
1472 {
1473  NS_LOG_FUNCTION(this);
1474 
1475  NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1476  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1477  {
1478  // Create a map of UT addresses and identifiers.
1480 
1481  // Enable statistics-related tags and trace sources on the device.
1482  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1483  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1484  NS_ASSERT(satDev != nullptr);
1485  Ptr<SatMac> satMac = satDev->GetMac();
1486  NS_ASSERT(satMac != nullptr);
1487  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1488  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1489  }
1490 
1491  // Connect to trace sources at GW nodes.
1492 
1493  NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1494  Callback<void, const Time&, const Address&> callback =
1495  MakeCallback(&SatStatsRtnMacJitterHelper::RxJitterCallback, this);
1496 
1497  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1498  {
1499  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1500 
1501  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1502  {
1503  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1504  NS_ASSERT(satDev != nullptr);
1505  Ptr<SatMac> satMac = satDev->GetMac();
1506  NS_ASSERT(satMac != nullptr);
1507 
1508  // Connect the object to the probe.
1509  if (satMac->TraceConnectWithoutContext("RxJitter", callback))
1510  {
1511  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1512  << " device #" << satDev->GetIfIndex());
1513 
1514  // Enable statistics-related tags and trace sources on the device.
1515  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1516  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1517  }
1518  else
1519  {
1520  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
1521  << " at node ID " << (*it)->GetId() << " device #"
1522  << satDev->GetIfIndex());
1523  }
1524 
1525  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1526 
1527  } // end of `for (NodeContainer::Iterator it = gws)`
1528 
1529 } // end of `void DoInstallProbes ();`
1530 
1531 // RETURN LINK PHY-LEVEL //////////////////////////////////////////////////////
1532 
1533 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnPhyJitterHelper);
1534 
1536  : SatStatsJitterHelper(satHelper)
1537 {
1538  NS_LOG_FUNCTION(this << satHelper);
1539 }
1540 
1542 {
1543  NS_LOG_FUNCTION(this);
1544 }
1545 
1546 TypeId // static
1548 {
1549  static TypeId tid = TypeId("ns3::SatStatsRtnPhyJitterHelper").SetParent<SatStatsJitterHelper>();
1550  return tid;
1551 }
1552 
1553 void
1555 {
1556  NS_LOG_FUNCTION(this);
1557 
1558  NodeContainer sats = Singleton<SatTopology>::Get()->GetOrbiterNodes();
1559 
1560  for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
1561  {
1562  Ptr<NetDevice> dev = GetSatSatOrbiterNetDevice(*it);
1563  Ptr<SatOrbiterNetDevice> satOrbiterDev = dev->GetObject<SatOrbiterNetDevice>();
1564  NS_ASSERT(satOrbiterDev != nullptr);
1565  std::map<uint32_t, Ptr<SatPhy>> satOrbiterFeederPhys = satOrbiterDev->GetFeederPhy();
1566  Ptr<SatPhy> satPhy;
1567  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterFeederPhys.begin();
1568  it2 != satOrbiterFeederPhys.end();
1569  ++it2)
1570  {
1571  satPhy = it2->second;
1572  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1573  }
1574  std::map<uint32_t, Ptr<SatPhy>> satOrbiterUserPhys = satOrbiterDev->GetUserPhy();
1575  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterUserPhys.begin();
1576  it2 != satOrbiterUserPhys.end();
1577  ++it2)
1578  {
1579  satPhy = it2->second;
1580  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1581  }
1582  } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
1583 
1584  NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1585  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1586  {
1587  // Create a map of UT addresses and identifiers.
1589 
1590  // Enable statistics-related tags and trace sources on the device.
1591  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1592  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1593  NS_ASSERT(satDev != nullptr);
1594  Ptr<SatPhy> satPhy = satDev->GetPhy();
1595  NS_ASSERT(satPhy != nullptr);
1596  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1597  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1598  }
1599 
1600  // Connect to trace sources at GW nodes.
1601 
1602  NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1603  Callback<void, const Time&, const Address&> callback =
1604  MakeCallback(&SatStatsRtnPhyJitterHelper::RxJitterCallback, this);
1605 
1606  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1607  {
1608  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1609 
1610  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1611  {
1612  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1613  NS_ASSERT(satDev != nullptr);
1614  Ptr<SatPhy> satPhy = satDev->GetPhy();
1615  NS_ASSERT(satPhy != nullptr);
1616 
1617  // Connect the object to the probe.
1618  if (satPhy->TraceConnectWithoutContext("RxJitter", callback))
1619  {
1620  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1621  << " device #" << satDev->GetIfIndex());
1622 
1623  // Enable statistics-related tags and trace sources on the device.
1624  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1625  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1626  }
1627  else
1628  {
1629  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
1630  << " at node ID " << (*it)->GetId() << " device #"
1631  << satDev->GetIfIndex());
1632  }
1633 
1634  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1635 
1636  } // end of `for (NodeContainer::Iterator it = gws)`
1637 
1638 } // end of `void DoInstallProbes ();`
1639 
1640 } // end of namespace ns3
SatNetDevice to be utilized in the UT and GW nodes.
SatOrbiterNetDevice to be utilized in geostationary satellite.
Time GetAndUpdatePreviousDelay(uint32_t identifier, Time newDelay)
Returns the previous delay mesurment for given identifier, and update with new value measured.
std::map< uint32_t, Time > m_previousDelayMap
Stores the last delay to a UT to compute jitter.
static TypeId GetTypeId()
inherited from ObjectBase base class
virtual void UpdateIdentifierOnProbes()
Change identifier used on probes, when handovers occur.
SatStatsFwdAppJitterHelper(Ptr< const SatHelper > satHelper)
virtual ~SatStatsFwdAppJitterHelper()
Destructor for SatStatsFwdAppJitterHelper.
std::map< Ptr< Probe >, std::pair< Ptr< Node >, uint32_t > > m_probes
Maintains a list of probes created by this helper.
static void RxCallback(Ptr< SatStatsFwdAppJitterHelper > 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.
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsFwdDevJitterHelper(Ptr< const SatHelper > satHelper)
virtual void UpdateIdentifierOnProbes()
Change identifier used on probes, when handovers occur.
std::map< Ptr< Probe >, std::pair< Ptr< Node >, uint32_t > > m_probes
Maintains a list of probes created by this helper.
SatStatsFwdMacJitterHelper(Ptr< const SatHelper > satHelper)
virtual void UpdateIdentifierOnProbes()
Change identifier used on probes, when handovers occur.
std::map< Ptr< Probe >, std::pair< Ptr< Node >, uint32_t > > m_probes
Maintains a list of probes created by this helper.
static TypeId GetTypeId()
inherited from ObjectBase base class
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsFwdPhyJitterHelper(Ptr< const SatHelper > satHelper)
virtual void UpdateIdentifierOnProbes()
Change identifier used on probes, when handovers occur.
std::map< Ptr< Probe >, std::pair< Ptr< Node >, uint32_t > > m_probes
Maintains a list of probes created by this helper.
Parent abstract class of all satellite statistics helpers.
static Ptr< NetDevice > GetSatSatOrbiterNetDevice(Ptr< Node > satNode)
uint32_t GetIdentifierForUtUser(Ptr< Node > utUserNode) const
static NetDeviceContainer GetGwSatNetDevice(Ptr< Node > gwNode)
virtual void SaveAddressAndIdentifier(Ptr< Node > utNode)
Save the address and the proper identifier from the given UT node.
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 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
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 jitter statistics helpers.
bool m_averagingMode
AveragingMode attribute.
bool DisconnectProbeFromCollector(Ptr< Probe > probe, uint32_t identifier)
Disconnect the probe from the right collector.
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsJitterHelper(Ptr< const SatHelper > satHelper)
void RxJitterCallback(const Time &jitter, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
void PassSampleToCollector(const Time &jitter, uint32_t identifier)
Find a collector with the right identifier and pass a sample data to it.
bool ConnectProbeToCollector(Ptr< Probe > probe, uint32_t identifier)
Connect the probe to the right collector.
Ptr< DataCollectionObject > m_aggregator
The aggregator created by this helper.
virtual void DoInstallProbes()=0
void SetAveragingMode(bool averagingMode)
CollectorMap m_terminalCollectors
Maintains a list of collectors created by this helper.
virtual ~SatStatsJitterHelper()
/ Destructor.
void DoInstall()
Install the probes, collectors, and aggregators necessary to produce the statistics output.
void InstallProbes()
Set up several probes or other means of listeners and connect them to the collectors.
Ptr< DistributionCollector > m_averagingCollector
The final collector utilized in averaged output (histogram, PDF, and CDF).
void SaveIpv4AddressAndIdentifier(Ptr< Node > utUserNode)
static TypeId GetTypeId()
inherited from ObjectBase base class
std::map< const Address, Time > m_previousDelayMap
Stores the last delay to a UT to compute jitter.
void RxCallback(Ptr< const Packet > packet, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
SatStatsRtnAppJitterHelper(Ptr< const SatHelper > satHelper)
void Ipv4Callback(const Time &jitter, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
SatStatsRtnDevJitterHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsRtnMacJitterHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsRtnPhyJitterHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.