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-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("SatStatsJitterHelper");
57 
58 namespace ns3
59 {
60 
61 NS_OBJECT_ENSURE_REGISTERED(SatStatsJitterHelper);
62 
63 SatStatsJitterHelper::SatStatsJitterHelper(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::SatStatsJitterHelper")
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(&SatStatsJitterHelper::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("jitter_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("jitter_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("jitter_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("jitter_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 jitter (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 jitter (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 jitter (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("SatStatsJitterHelper - 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 SatStatsJitterHelper::RxJitterCallback(const Time& jitter, const Address& from)
419 {
420  // NS_LOG_FUNCTION (this << jitter.GetSeconds () << from);
421 
422  if (from.IsInvalid())
423  {
424  NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.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(jitter, it->second);
436  }
437  else
438  {
439  NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.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 SatStatsJitterHelper::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 SatStatsJitterHelper::PassSampleToCollector(const Time& jitter, uint32_t identifier)
534 {
535  // NS_LOG_FUNCTION (this << jitter.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, jitter.GetSeconds());
547  break;
548  }
549 
552  Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
553  NS_ASSERT(c != nullptr);
554  c->TraceSinkDouble(0.0, jitter.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, jitter.GetSeconds());
569  }
570  else
571  {
572  Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
573  NS_ASSERT(c != nullptr);
574  c->TraceSinkDouble(0.0, jitter.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(SatStatsFwdAppJitterHelper);
590 
592  : SatStatsJitterHelper(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::SatStatsFwdAppJitterHelper").SetParent<SatStatsJitterHelper>();
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 RxJitter trace sources, and some other
628  * applications support Rx trace sources. Below we support both ways.
629  */
630  if (app->GetInstanceTypeId().LookupTraceSourceByName("RxJitter") != nullptr)
631  {
632  NS_LOG_INFO(this << " attempt to connect using RxJitter");
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("RxJitter", 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(&SatStatsFwdAppJitterHelper::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  * RxJitter 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 jitter 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 jitter 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 Time
702 SatStatsFwdAppJitterHelper::GetAndUpdatePreviousDelay(uint32_t identifier, Time newDelay)
703 {
704  NS_LOG_FUNCTION(identifier);
705 
706  Time delay = Seconds(0);
707  std::map<uint32_t, Time>::iterator it = m_previousDelayMap.find(identifier);
708  if (it != m_previousDelayMap.end())
709  {
710  delay = it->second;
711  }
712  m_previousDelayMap[identifier] = newDelay;
713  return delay;
714 }
715 
716 void // static
717 SatStatsFwdAppJitterHelper::RxCallback(Ptr<SatStatsFwdAppJitterHelper> helper,
718  uint32_t identifier,
719  Ptr<const Packet> packet,
720  const Address& from)
721 {
722  NS_LOG_FUNCTION(helper << identifier << packet << packet->GetSize() << from);
723 
724  TrafficTimeTag timeTag;
725  if (packet->PeekPacketTag(timeTag))
726  {
727  NS_LOG_DEBUG("Contains a TrafficTimeTag tag");
728  const Time delay = Simulator::Now() - timeTag.GetSenderTimestamp();
729  Time previousDelay = helper->GetAndUpdatePreviousDelay(identifier, delay);
730  if (previousDelay.IsZero() == false)
731  {
732  Time jitter = Abs(delay - previousDelay);
733  helper->PassSampleToCollector(jitter, identifier);
734  }
735  }
736  else
737  {
738  NS_LOG_WARN("Discarding a packet of " << packet->GetSize() << " from statistics collection"
739  << " because it does not contain any TrafficTimeTag");
740  }
741 }
742 
743 // FORWARD LINK DEVICE-LEVEL //////////////////////////////////////////////////
744 
745 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdDevJitterHelper);
746 
748  : SatStatsJitterHelper(satHelper)
749 {
750  NS_LOG_FUNCTION(this << satHelper);
751 }
752 
754 {
755  NS_LOG_FUNCTION(this);
756 }
757 
758 TypeId // static
760 {
761  static TypeId tid = TypeId("ns3::SatStatsFwdDevJitterHelper").SetParent<SatStatsJitterHelper>();
762  return tid;
763 }
764 
765 void
767 {
768  NS_LOG_FUNCTION(this);
769  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
770 
771  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
772  {
773  const int32_t utId = GetUtId(*it);
774  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
775  const uint32_t identifier = GetIdentifierForUt(*it);
776 
777  // Create the probe.
778  std::ostringstream probeName;
779  probeName << utId;
780  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
781  probe->SetName(probeName.str());
782 
783  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
784 
785  // Connect the object to the probe.
786  if (probe->ConnectByObject("RxJitter", dev) && ConnectProbeToCollector(probe, identifier))
787  {
788  m_probes.push_back(probe->GetObject<Probe>());
789 
790  // Enable statistics-related tags and trace sources on the device.
791  dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
792  }
793  else
794  {
795  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
796  << " at node ID " << (*it)->GetId() << " device #2");
797  }
798 
799  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
800 
801  // Enable statistics-related tags on the transmitting device.
802  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
803  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
804  {
805  NetDeviceContainer devs = GetGwSatNetDevice(*it);
806 
807  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
808  {
809  NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
810  (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
811  }
812  }
813 
814 } // end of `void DoInstallProbes ();`
815 
816 // FORWARD LINK MAC-LEVEL /////////////////////////////////////////////////////
817 
818 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdMacJitterHelper);
819 
821  : SatStatsJitterHelper(satHelper)
822 {
823  NS_LOG_FUNCTION(this << satHelper);
824 }
825 
827 {
828  NS_LOG_FUNCTION(this);
829 }
830 
831 TypeId // static
833 {
834  static TypeId tid = TypeId("ns3::SatStatsFwdMacJitterHelper").SetParent<SatStatsJitterHelper>();
835  return tid;
836 }
837 
838 void
840 {
841  NS_LOG_FUNCTION(this);
842  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
843 
844  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
845  {
846  const int32_t utId = GetUtId(*it);
847  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
848  const uint32_t identifier = GetIdentifierForUt(*it);
849 
850  // Create the probe.
851  std::ostringstream probeName;
852  probeName << utId;
853  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
854  probe->SetName(probeName.str());
855 
856  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
857  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
858  NS_ASSERT(satDev != nullptr);
859  Ptr<SatMac> satMac = satDev->GetMac();
860  NS_ASSERT(satMac != nullptr);
861 
862  // Connect the object to the probe.
863  if (probe->ConnectByObject("RxJitter", satMac) &&
864  ConnectProbeToCollector(probe, identifier))
865  {
866  m_probes.push_back(probe->GetObject<Probe>());
867 
868  // Enable statistics-related tags and trace sources on the device.
869  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
870  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
871  }
872  else
873  {
874  NS_FATAL_ERROR("Error connecting to RxJitter trace source of satMac"
875  << " at node ID " << (*it)->GetId() << " device #2");
876  }
877 
878  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
879 
880  // Enable statistics-related tags on the transmitting device.
881  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
882  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
883  {
884  NetDeviceContainer devs = GetGwSatNetDevice(*it);
885 
886  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
887  {
888  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
889  NS_ASSERT(satDev != nullptr);
890  Ptr<SatMac> satMac = satDev->GetMac();
891  NS_ASSERT(satMac != nullptr);
892 
893  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
894  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
895  }
896  }
897 
898 } // end of `void DoInstallProbes ();`
899 
900 // FORWARD LINK PHY-LEVEL /////////////////////////////////////////////////////
901 
902 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdPhyJitterHelper);
903 
905  : SatStatsJitterHelper(satHelper)
906 {
907  NS_LOG_FUNCTION(this << satHelper);
908 }
909 
911 {
912  NS_LOG_FUNCTION(this);
913 }
914 
915 TypeId // static
917 {
918  static TypeId tid = TypeId("ns3::SatStatsFwdPhyJitterHelper").SetParent<SatStatsJitterHelper>();
919  return tid;
920 }
921 
922 void
924 {
925  NS_LOG_FUNCTION(this);
926 
927  NodeContainer sats = GetSatHelper()->GetBeamHelper()->GetGeoSatNodes();
928 
929  for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
930  {
931  Ptr<NetDevice> dev = GetSatSatGeoNetDevice(*it);
932  Ptr<SatGeoNetDevice> satGeoDev = dev->GetObject<SatGeoNetDevice>();
933  NS_ASSERT(satGeoDev != nullptr);
934  std::map<uint32_t, Ptr<SatPhy>> satGeoFeederPhys = satGeoDev->GetFeederPhy();
935  Ptr<SatPhy> satPhy;
936  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satGeoFeederPhys.begin();
937  it2 != satGeoFeederPhys.end();
938  ++it2)
939  {
940  satPhy = it2->second;
941  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
942  }
943  std::map<uint32_t, Ptr<SatPhy>> satGeoUserPhys = satGeoDev->GetUserPhy();
944  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satGeoUserPhys.begin();
945  it2 != satGeoUserPhys.end();
946  ++it2)
947  {
948  satPhy = it2->second;
949  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
950  }
951  } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
952 
953  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
954 
955  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
956  {
957  const int32_t utId = GetUtId(*it);
958  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
959  const uint32_t identifier = GetIdentifierForUt(*it);
960 
961  // Create the probe.
962  std::ostringstream probeName;
963  probeName << utId;
964  Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
965  probe->SetName(probeName.str());
966 
967  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
968  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
969  NS_ASSERT(satDev != nullptr);
970  Ptr<SatPhy> satPhy = satDev->GetPhy();
971  NS_ASSERT(satPhy != nullptr);
972 
973  // Connect the object to the probe.
974  if (probe->ConnectByObject("RxJitter", satPhy) &&
975  ConnectProbeToCollector(probe, identifier))
976  {
977  m_probes.push_back(probe->GetObject<Probe>());
978 
979  // Enable statistics-related tags and trace sources on the device.
980  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
981  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
982  }
983  else
984  {
985  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatPhy"
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 = GetSatHelper()->GetBeamHelper()->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<SatPhy> satPhy = satDev->GetPhy();
1002  NS_ASSERT(satPhy != nullptr);
1003 
1004  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1005  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1006  }
1007  }
1008 
1009 } // end of `void DoInstallProbes ();`
1010 
1011 // RETURN LINK APPLICATION-LEVEL //////////////////////////////////////////////
1012 
1013 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnAppJitterHelper);
1014 
1016  : SatStatsJitterHelper(satHelper)
1017 {
1018  NS_LOG_FUNCTION(this << satHelper);
1019 }
1020 
1022 {
1023  NS_LOG_FUNCTION(this);
1024 }
1025 
1026 TypeId // static
1028 {
1029  static TypeId tid = TypeId("ns3::SatStatsRtnAppJitterHelper").SetParent<SatStatsJitterHelper>();
1030  return tid;
1031 }
1032 
1033 void
1035 {
1036  NS_LOG_FUNCTION(this);
1037 
1038  NodeContainer utUsers = GetSatHelper()->GetUtUsers();
1039  for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
1040  {
1041  // Create a map of UT user addresses and identifiers.
1043 
1044  /*
1045  * Some sender applications might need a special attribute to be enabled
1046  * before jitter statistics can be computed. We enable it here.
1047  */
1048  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1049  {
1050  Ptr<Application> app = (*it)->GetApplication(i);
1051 
1052  if (!app->SetAttributeFailSafe("EnableStatisticsTags", BooleanValue(true)))
1053  {
1054  NS_LOG_WARN(this << " node ID " << (*it)->GetId() << " application #" << i
1055  << " might not produce the required tags"
1056  << " in the transmitted packets,"
1057  << " thus preventing jitter statistics"
1058  << " from this sender application");
1059  }
1060 
1061  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1062 
1063  } // end of `for (NodeContainer::Iterator it: utUsers)`
1064 
1065  // Connect to trace sources at GW user node's applications.
1066 
1067  NodeContainer gwUsers = GetSatHelper()->GetGwUsers();
1068  Callback<void, const Time&, const Address&> rxJitterCallback =
1069  MakeCallback(&SatStatsRtnAppJitterHelper::Ipv4Callback, this);
1070  Callback<void, Ptr<const Packet>, const Address&> rxCallback =
1071  MakeCallback(&SatStatsRtnAppJitterHelper::RxCallback, this);
1072 
1073  for (NodeContainer::Iterator it = gwUsers.Begin(); it != gwUsers.End(); ++it)
1074  {
1075  for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1076  {
1077  Ptr<Application> app = (*it)->GetApplication(i);
1078  bool isConnected = false;
1079 
1080  /*
1081  * Some applications support RxJitter trace sources, and some other
1082  * applications support Rx trace sources. Below we support both ways.
1083  */
1084  if (app->GetInstanceTypeId().LookupTraceSourceByName("RxJitter") != nullptr)
1085  {
1086  isConnected = app->TraceConnectWithoutContext("RxJitter", rxJitterCallback);
1087  }
1088  else if (app->GetInstanceTypeId().LookupTraceSourceByName("Rx") != nullptr)
1089  {
1090  isConnected = app->TraceConnectWithoutContext("Rx", rxCallback);
1091  }
1092 
1093  if (isConnected)
1094  {
1095  NS_LOG_INFO(this << " successfully connected"
1096  << " with node ID " << (*it)->GetId() << " application #" << i);
1097  }
1098  else
1099  {
1100  /*
1101  * We're being tolerant here by only logging a warning, because
1102  * not every kind of Application is equipped with the expected
1103  * RxJitter or Rx trace source.
1104  */
1105  NS_LOG_WARN(this << " unable to connect"
1106  << " with node ID " << (*it)->GetId() << " application #" << i);
1107  }
1108 
1109  } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1110 
1111  } // end of `for (NodeContainer::Iterator it: gwUsers)`
1112 
1113 } // end of `void DoInstallProbes ();`
1114 
1115 void
1116 SatStatsRtnAppJitterHelper::RxCallback(Ptr<const Packet> packet, const Address& from)
1117 {
1118  TrafficTimeTag timeTag;
1119  if (packet->PeekPacketTag(timeTag))
1120  {
1121  NS_LOG_DEBUG(this << " contains a TrafficTimeTag tag");
1122  const Time delay = Simulator::Now() - timeTag.GetSenderTimestamp();
1123  const Address identifier = InetSocketAddress::ConvertFrom(from).GetIpv4();
1124  std::map<const Address, Time>::iterator it = m_previousDelayMap.find(identifier);
1125  if (it != m_previousDelayMap.end())
1126  {
1127  Time previousDelay = it->second;
1128  Time jitter = Abs(delay - previousDelay);
1129  Ipv4Callback(jitter, from);
1130  }
1131  m_previousDelayMap[identifier] = delay;
1132  }
1133  else
1134  {
1135  NS_LOG_WARN(this << " discarding a packet of " << packet->GetSize()
1136  << " from statistics collection"
1137  << " because it does not contain any TrafficTimeTag");
1138  }
1139 } // end of `void RxCallback (Ptr<const Packet>, const Address);`
1140 
1141 void
1142 SatStatsRtnAppJitterHelper::Ipv4Callback(const Time& jitter, const Address& from)
1143 {
1144  // NS_LOG_FUNCTION (this << Time.GetSeconds () << from);
1145 
1146  if (InetSocketAddress::IsMatchingType(from))
1147  {
1148  // Determine the identifier associated with the sender address.
1149  const Address ipv4Addr = InetSocketAddress::ConvertFrom(from).GetIpv4();
1150  std::map<const Address, uint32_t>::const_iterator it1 = m_identifierMap.find(ipv4Addr);
1151 
1152  if (it1 == m_identifierMap.end())
1153  {
1154  NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.GetSeconds()
1155  << " from statistics collection because of"
1156  << " unknown sender IPV4 address " << ipv4Addr);
1157  }
1158  else
1159  {
1160  PassSampleToCollector(jitter, it1->second);
1161  }
1162  }
1163  else
1164  {
1165  NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.GetSeconds()
1166  << " from statistics collection"
1167  << " because it comes from sender " << from
1168  << " without valid InetSocketAddress");
1169  }
1170 }
1171 
1172 void
1174 {
1175  NS_LOG_FUNCTION(this << utUserNode->GetId());
1176 
1177  Ptr<Ipv4> ipv4 = utUserNode->GetObject<Ipv4>();
1178 
1179  if (ipv4 == nullptr)
1180  {
1181  NS_LOG_INFO(this << " Node " << utUserNode->GetId() << " does not support IPv4 protocol");
1182  }
1183  else if (ipv4->GetNInterfaces() >= 2)
1184  {
1185  const uint32_t identifier = GetIdentifierForUtUser(utUserNode);
1186 
1187  /*
1188  * Assuming that #0 is for loopback interface and #1 is for subscriber
1189  * network interface.
1190  */
1191  for (uint32_t i = 0; i < ipv4->GetNAddresses(1); i++)
1192  {
1193  const Address addr = ipv4->GetAddress(1, i).GetLocal();
1194  m_identifierMap[addr] = identifier;
1195  NS_LOG_INFO(this << " associated address " << addr << " with identifier "
1196  << identifier);
1197  }
1198  }
1199  else
1200  {
1201  NS_LOG_WARN(this << " Node " << utUserNode->GetId() << " is not a valid UT user");
1202  }
1203 }
1204 
1205 // RETURN LINK DEVICE-LEVEL ///////////////////////////////////////////////////
1206 
1207 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnDevJitterHelper);
1208 
1210  : SatStatsJitterHelper(satHelper)
1211 {
1212  NS_LOG_FUNCTION(this << satHelper);
1213 }
1214 
1216 {
1217  NS_LOG_FUNCTION(this);
1218 }
1219 
1220 TypeId // static
1222 {
1223  static TypeId tid = TypeId("ns3::SatStatsRtnDevJitterHelper").SetParent<SatStatsJitterHelper>();
1224  return tid;
1225 }
1226 
1227 void
1229 {
1230  NS_LOG_FUNCTION(this);
1231 
1232  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
1233  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1234  {
1235  // Create a map of UT addresses and identifiers.
1237 
1238  // Enable statistics-related tags and trace sources on the device.
1239  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1240  dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1241  }
1242 
1243  // Connect to trace sources at GW nodes.
1244 
1245  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
1246  Callback<void, const Time&, const Address&> callback =
1247  MakeCallback(&SatStatsRtnDevJitterHelper::RxJitterCallback, this);
1248 
1249  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1250  {
1251  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1252 
1253  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1254  {
1255  NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
1256 
1257  if ((*itDev)->TraceConnectWithoutContext("RxJitter", callback))
1258  {
1259  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1260  << " device #" << (*itDev)->GetIfIndex());
1261 
1262  // Enable statistics-related tags and trace sources on the device.
1263  (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1264  }
1265  else
1266  {
1267  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
1268  << " at node ID " << (*it)->GetId() << " device #"
1269  << (*itDev)->GetIfIndex());
1270  }
1271 
1272  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1273 
1274  } // end of `for (NodeContainer::Iterator it = gws)`
1275 
1276 } // end of `void DoInstallProbes ();`
1277 
1278 // RETURN LINK MAC-LEVEL //////////////////////////////////////////////////////
1279 
1280 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnMacJitterHelper);
1281 
1283  : SatStatsJitterHelper(satHelper)
1284 {
1285  NS_LOG_FUNCTION(this << satHelper);
1286 }
1287 
1289 {
1290  NS_LOG_FUNCTION(this);
1291 }
1292 
1293 TypeId // static
1295 {
1296  static TypeId tid = TypeId("ns3::SatStatsRtnMacJitterHelper").SetParent<SatStatsJitterHelper>();
1297  return tid;
1298 }
1299 
1300 void
1302 {
1303  NS_LOG_FUNCTION(this);
1304 
1305  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
1306  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1307  {
1308  // Create a map of UT addresses and identifiers.
1310 
1311  // Enable statistics-related tags and trace sources on the device.
1312  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1313  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1314  NS_ASSERT(satDev != nullptr);
1315  Ptr<SatMac> satMac = satDev->GetMac();
1316  NS_ASSERT(satMac != nullptr);
1317  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1318  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1319  }
1320 
1321  // Connect to trace sources at GW nodes.
1322 
1323  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
1324  Callback<void, const Time&, const Address&> callback =
1325  MakeCallback(&SatStatsRtnMacJitterHelper::RxJitterCallback, this);
1326 
1327  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1328  {
1329  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1330 
1331  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1332  {
1333  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1334  NS_ASSERT(satDev != nullptr);
1335  Ptr<SatMac> satMac = satDev->GetMac();
1336  NS_ASSERT(satMac != nullptr);
1337 
1338  // Connect the object to the probe.
1339  if (satMac->TraceConnectWithoutContext("RxJitter", callback))
1340  {
1341  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1342  << " device #" << satDev->GetIfIndex());
1343 
1344  // Enable statistics-related tags and trace sources on the device.
1345  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1346  satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1347  }
1348  else
1349  {
1350  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
1351  << " at node ID " << (*it)->GetId() << " device #"
1352  << satDev->GetIfIndex());
1353  }
1354 
1355  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1356 
1357  } // end of `for (NodeContainer::Iterator it = gws)`
1358 
1359 } // end of `void DoInstallProbes ();`
1360 
1361 // RETURN LINK PHY-LEVEL //////////////////////////////////////////////////////
1362 
1363 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnPhyJitterHelper);
1364 
1366  : SatStatsJitterHelper(satHelper)
1367 {
1368  NS_LOG_FUNCTION(this << satHelper);
1369 }
1370 
1372 {
1373  NS_LOG_FUNCTION(this);
1374 }
1375 
1376 TypeId // static
1378 {
1379  static TypeId tid = TypeId("ns3::SatStatsRtnPhyJitterHelper").SetParent<SatStatsJitterHelper>();
1380  return tid;
1381 }
1382 
1383 void
1385 {
1386  NS_LOG_FUNCTION(this);
1387 
1388  NodeContainer sats = GetSatHelper()->GetBeamHelper()->GetGeoSatNodes();
1389 
1390  for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
1391  {
1392  Ptr<NetDevice> dev = GetSatSatGeoNetDevice(*it);
1393  Ptr<SatGeoNetDevice> satGeoDev = dev->GetObject<SatGeoNetDevice>();
1394  NS_ASSERT(satGeoDev != nullptr);
1395  std::map<uint32_t, Ptr<SatPhy>> satGeoFeederPhys = satGeoDev->GetFeederPhy();
1396  Ptr<SatPhy> satPhy;
1397  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satGeoFeederPhys.begin();
1398  it2 != satGeoFeederPhys.end();
1399  ++it2)
1400  {
1401  satPhy = it2->second;
1402  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1403  }
1404  std::map<uint32_t, Ptr<SatPhy>> satGeoUserPhys = satGeoDev->GetUserPhy();
1405  for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satGeoUserPhys.begin();
1406  it2 != satGeoUserPhys.end();
1407  ++it2)
1408  {
1409  satPhy = it2->second;
1410  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1411  }
1412  } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
1413 
1414  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
1415  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1416  {
1417  // Create a map of UT addresses and identifiers.
1419 
1420  // Enable statistics-related tags and trace sources on the device.
1421  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1422  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1423  NS_ASSERT(satDev != nullptr);
1424  Ptr<SatPhy> satPhy = satDev->GetPhy();
1425  NS_ASSERT(satPhy != nullptr);
1426  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1427  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1428  }
1429 
1430  // Connect to trace sources at GW nodes.
1431 
1432  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
1433  Callback<void, const Time&, const Address&> callback =
1434  MakeCallback(&SatStatsRtnPhyJitterHelper::RxJitterCallback, this);
1435 
1436  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1437  {
1438  NetDeviceContainer devs = GetGwSatNetDevice(*it);
1439 
1440  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1441  {
1442  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1443  NS_ASSERT(satDev != nullptr);
1444  Ptr<SatPhy> satPhy = satDev->GetPhy();
1445  NS_ASSERT(satPhy != nullptr);
1446 
1447  // Connect the object to the probe.
1448  if (satPhy->TraceConnectWithoutContext("RxJitter", callback))
1449  {
1450  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1451  << " device #" << satDev->GetIfIndex());
1452 
1453  // Enable statistics-related tags and trace sources on the device.
1454  satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1455  satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1456  }
1457  else
1458  {
1459  NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
1460  << " at node ID " << (*it)->GetId() << " device #"
1461  << satDev->GetIfIndex());
1462  }
1463 
1464  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1465 
1466  } // end of `for (NodeContainer::Iterator it = gws)`
1467 
1468 } // end of `void DoInstallProbes ();`
1469 
1470 } // 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.
Time GetAndUpdatePreviousDelay(uint32_t identifier, Time newDelay)
Returns the previous delay mesurment for given identifier, and update with new value measured.
std::list< Ptr< Probe > > m_probes
Maintains a list of probes created by this helper.
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
SatStatsFwdAppJitterHelper(Ptr< const SatHelper > satHelper)
virtual ~SatStatsFwdAppJitterHelper()
Destructor for SatStatsFwdAppJitterHelper.
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)
std::list< Ptr< Probe > > m_probes
Maintains a list of probes created by this helper.
std::list< Ptr< Probe > > m_probes
Maintains a list of probes created by this helper.
SatStatsFwdMacJitterHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsFwdPhyJitterHelper(Ptr< const SatHelper > satHelper)
std::list< Ptr< Probe > > m_probes
Maintains a list of probes created by this helper.
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
Base class for jitter statistics helpers.
bool m_averagingMode
AveragingMode attribute.
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.
std::map< const Address, uint32_t > m_identifierMap
Map of address and the identifier associated with it (for return link).
void SaveAddressAndIdentifier(Ptr< Node > utNode)
Save the address and the proper identifier from the given UT node.
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)
Save the IPv4 address and the proper identifier from the given UT user node.
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.