Loading...
Searching...
No Matches
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
60NS_LOG_COMPONENT_DEFINE("SatStatsJitterHelper");
61
62namespace ns3
63{
64
65NS_OBJECT_ENSURE_REGISTERED(SatStatsJitterHelper);
66
67SatStatsJitterHelper::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
79TypeId // 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
95void
97{
98 NS_LOG_FUNCTION(this << averagingMode);
99 m_averagingMode = averagingMode;
100}
101
102bool
107
108void
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",
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",
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",
253 &MultiFileAggregator::Write2d);
254 m_terminalCollectors.ConnectToAggregator("OutputString",
256 &MultiFileAggregator::AddContextHeading);
257 m_terminalCollectors.ConnectToAggregator("Warning",
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",
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",
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.
411
412} // end of `void DoInstall ();`
413
414void
416{
417 // The method below is supposed to be implemented by the child class.
419}
420
421void
422SatStatsJitterHelper::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" << " invalid sender address");
430 }
431 else
432 {
433 // Determine the identifier associated with the sender address.
434 std::map<const Address, uint32_t>::const_iterator it = m_identifierMap.find(from);
435
436 if (it != m_identifierMap.end())
437 {
438 PassSampleToCollector(jitter, it->second);
439 }
440 else
441 {
442 NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.GetSeconds()
443 << " from statistics collection because of"
444 << " unknown sender address " << from);
445 }
446 }
447}
448
449bool
450SatStatsJitterHelper::ConnectProbeToCollector(Ptr<Probe> probe, uint32_t identifier)
451{
452 NS_LOG_FUNCTION(this << probe << probe->GetName() << identifier);
453
454 bool ret = false;
455 switch (GetOutputType())
456 {
459 ret = m_terminalCollectors.ConnectWithProbe(probe,
460 "OutputSeconds",
461 identifier,
462 &ScalarCollector::TraceSinkDouble);
463 break;
464
467 ret = m_terminalCollectors.ConnectWithProbe(probe,
468 "OutputSeconds",
469 identifier,
470 &UnitConversionCollector::TraceSinkDouble);
471 break;
472
479 if (m_averagingMode)
480 {
481 ret = m_terminalCollectors.ConnectWithProbe(probe,
482 "OutputSeconds",
483 identifier,
484 &ScalarCollector::TraceSinkDouble);
485 }
486 else
487 {
488 ret = m_terminalCollectors.ConnectWithProbe(probe,
489 "OutputSeconds",
490 identifier,
491 &DistributionCollector::TraceSinkDouble);
492 }
493 break;
494
495 default:
496 NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
497 << " is not a valid output type for this statistics.");
498 break;
499 }
500
501 if (ret)
502 {
503 NS_LOG_INFO(this << " created probe " << probe->GetName() << ", connected to collector "
504 << identifier);
505 }
506 else
507 {
508 NS_LOG_WARN(this << " unable to connect probe " << probe->GetName() << " to collector "
509 << identifier);
510 }
511
512 return ret;
513}
514
515bool
516SatStatsJitterHelper::DisconnectProbeFromCollector(Ptr<Probe> probe, uint32_t identifier)
517{
518 NS_LOG_FUNCTION(this << probe << probe->GetName() << identifier);
519
520 bool ret = false;
521 switch (GetOutputType())
522 {
525 ret = m_terminalCollectors.DisconnectWithProbe(probe,
526 "OutputSeconds",
527 identifier,
528 &ScalarCollector::TraceSinkDouble);
529 break;
530
533 ret = m_terminalCollectors.DisconnectWithProbe(probe,
534 "OutputSeconds",
535 identifier,
536 &UnitConversionCollector::TraceSinkDouble);
537 break;
538
545 if (m_averagingMode)
546 {
547 ret = m_terminalCollectors.DisconnectWithProbe(probe,
548 "OutputSeconds",
549 identifier,
550 &ScalarCollector::TraceSinkDouble);
551 }
552 else
553 {
554 ret = m_terminalCollectors.DisconnectWithProbe(probe,
555 "OutputSeconds",
556 identifier,
557 &DistributionCollector::TraceSinkDouble);
558 }
559 break;
560
561 default:
562 NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
563 << " is not a valid output type for this statistics.");
564 break;
565 }
566
567 if (ret)
568 {
569 NS_LOG_INFO(this << " probe " << probe->GetName() << ", disconnected from collector "
570 << identifier);
571 }
572 else
573 {
574 NS_LOG_WARN(this << " unable to disconnect probe " << probe->GetName() << " from collector "
575 << identifier);
576 }
577
578 return ret;
579}
580
581void
582SatStatsJitterHelper::PassSampleToCollector(const Time& jitter, uint32_t identifier)
583{
584 // NS_LOG_FUNCTION (this << jitter.GetSeconds () << identifier);
585
586 Ptr<DataCollectionObject> collector = m_terminalCollectors.Get(identifier);
587 NS_ASSERT_MSG(collector != nullptr, "Unable to find collector with identifier " << identifier);
588
589 switch (GetOutputType())
590 {
593 Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
594 NS_ASSERT(c != nullptr);
595 c->TraceSinkDouble(0.0, jitter.GetSeconds());
596 break;
597 }
598
601 Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
602 NS_ASSERT(c != nullptr);
603 c->TraceSinkDouble(0.0, jitter.GetSeconds());
604 break;
605 }
606
613 if (m_averagingMode)
614 {
615 Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
616 NS_ASSERT(c != nullptr);
617 c->TraceSinkDouble(0.0, jitter.GetSeconds());
618 }
619 else
620 {
621 Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
622 NS_ASSERT(c != nullptr);
623 c->TraceSinkDouble(0.0, jitter.GetSeconds());
624 }
625 break;
626
627 default:
628 NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
629 << " is not a valid output type for this statistics.");
630 break;
631
632 } // end of `switch (GetOutputType ())`
633
634} // end of `void PassSampleToCollector (Time, uint32_t)`
635
636// FORWARD LINK APPLICATION-LEVEL /////////////////////////////////////////////
637
638NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdAppJitterHelper);
639
641 : SatStatsJitterHelper(satHelper)
642{
643 NS_LOG_FUNCTION(this << satHelper);
644}
645
647{
648 NS_LOG_FUNCTION(this);
649}
650
651TypeId // static
653{
654 static TypeId tid = TypeId("ns3::SatStatsFwdAppJitterHelper").SetParent<SatStatsJitterHelper>();
655 return tid;
656}
657
658void
660{
661 NS_LOG_FUNCTION(this);
662 NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtUserNodes();
663
664 for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
665 {
666 const int32_t utUserId = GetUtUserId(*it);
667 NS_ASSERT_MSG(utUserId > 0, "Node " << (*it)->GetId() << " is not a valid UT user");
668 const uint32_t identifier = GetIdentifierForUtUser(*it);
669
670 for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
671 {
672 Ptr<Application> app = (*it)->GetApplication(i);
673 bool isConnected = false;
674
675 /*
676 * Some applications support RxJitter trace sources, and some other
677 * applications support Rx trace sources. Below we support both ways.
678 */
679 if (app->GetInstanceTypeId().LookupTraceSourceByName("RxJitter") != nullptr)
680 {
681 NS_LOG_INFO(this << " attempt to connect using RxJitter");
682
683 // Create the probe.
684 std::ostringstream probeName;
685 probeName << utUserId << "-" << i;
686 Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
687 probe->SetName(probeName.str());
688
689 // Connect the object to the probe.
690 if (probe->ConnectByObject("RxJitter", app))
691 {
692 isConnected = ConnectProbeToCollector(probe, identifier);
693 m_probes.insert(
694 std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
695 }
696 }
697 else if (app->GetInstanceTypeId().LookupTraceSourceByName("Rx") != nullptr)
698 {
699 NS_LOG_INFO(this << " attempt to connect using Rx");
700 Callback<void, Ptr<const Packet>, const Address&> rxCallback =
701 MakeBoundCallback(&SatStatsFwdAppJitterHelper::RxCallback, this, identifier);
702 isConnected = app->TraceConnectWithoutContext("Rx", rxCallback);
703 }
704
705 if (isConnected)
706 {
707 NS_LOG_INFO(this << " successfully connected" << " with node ID " << (*it)->GetId()
708 << " application #" << i);
709 }
710 else
711 {
712 /*
713 * We're being tolerant here by only logging a warning, because
714 * not every kind of Application is equipped with the expected
715 * RxJitter or Rx trace source.
716 */
717 NS_LOG_WARN(this << " unable to connect" << " with node ID " << (*it)->GetId()
718 << " application #" << i);
719 }
720
721 } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
722
723 } // end of `for (it = utUsers.Begin(); it != utUsers.End (); ++it)`
724
725 /*
726 * Some sender applications might need a special attribute to be enabled
727 * before jitter statistics can be computed. We enable it here.
728 */
729 NodeContainer gwUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
730 for (NodeContainer::Iterator it = gwUsers.Begin(); it != gwUsers.End(); ++it)
731 {
732 for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
733 {
734 Ptr<Application> app = (*it)->GetApplication(i);
735
736 if (!app->SetAttributeFailSafe("EnableStatisticsTags", BooleanValue(true)))
737 {
738 NS_LOG_WARN(this << " node ID " << (*it)->GetId() << " application #" << i
739 << " might not produce the required tags"
740 << " in the packets it transmits,"
741 << " thus preventing jitter statistics"
742 << " from this application");
743 }
744
745 } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
746
747 } // end of `for (it = gwUsers.Begin(); it != gwUsers.End (); ++it)`
748
749} // end of `void DoInstallProbes ();`
750
751void
753{
754 NS_LOG_FUNCTION(this);
755
756 std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
757
758 for (it = m_probes.begin(); it != m_probes.end(); it++)
759 {
760 Ptr<Probe> probe = it->first;
761 Ptr<Node> node = it->second.first;
762 uint32_t identifier = it->second.second;
763
764 if (!DisconnectProbeFromCollector(probe, identifier))
765 {
766 NS_FATAL_ERROR("Error disconnecting trace file on handover");
767 }
768
769 identifier = GetIdentifierForUtUser(node);
770
771 if (!ConnectProbeToCollector(probe, identifier))
772 {
773 NS_FATAL_ERROR("Error connecting trace file on handover");
774 }
775
776 it->second.second = identifier;
777 }
778} // end of `void UpdateIdentifierOnProbes ();`
779
780Time
782{
783 NS_LOG_FUNCTION(identifier);
784
785 Time delay = Seconds(0);
786 std::map<uint32_t, Time>::iterator it = m_previousDelayMap.find(identifier);
787 if (it != m_previousDelayMap.end())
788 {
789 delay = it->second;
790 }
791 m_previousDelayMap[identifier] = newDelay;
792 return delay;
793}
794
795void // static
796SatStatsFwdAppJitterHelper::RxCallback(Ptr<SatStatsFwdAppJitterHelper> helper,
797 uint32_t identifier,
798 Ptr<const Packet> packet,
799 const Address& from)
800{
801 NS_LOG_FUNCTION(helper << identifier << packet << packet->GetSize() << from);
802
803 TrafficTimeTag timeTag;
804 if (packet->PeekPacketTag(timeTag))
805 {
806 NS_LOG_DEBUG("Contains a TrafficTimeTag tag");
807 const Time delay = Simulator::Now() - timeTag.GetSenderTimestamp();
808 Time previousDelay = helper->GetAndUpdatePreviousDelay(identifier, delay);
809 if (previousDelay.IsZero() == false)
810 {
811 Time jitter = Abs(delay - previousDelay);
812 helper->PassSampleToCollector(jitter, identifier);
813 }
814 }
815 else
816 {
817 NS_LOG_WARN("Discarding a packet of " << packet->GetSize() << " from statistics collection"
818 << " because it does not contain any TrafficTimeTag");
819 }
820}
821
822// FORWARD LINK DEVICE-LEVEL //////////////////////////////////////////////////
823
824NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdDevJitterHelper);
825
827 : SatStatsJitterHelper(satHelper)
828{
829 NS_LOG_FUNCTION(this << satHelper);
830}
831
833{
834 NS_LOG_FUNCTION(this);
835}
836
837TypeId // static
839{
840 static TypeId tid = TypeId("ns3::SatStatsFwdDevJitterHelper").SetParent<SatStatsJitterHelper>();
841 return tid;
842}
843
844void
846{
847 NS_LOG_FUNCTION(this);
848 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
849
850 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
851 {
852 const int32_t utId = GetUtId(*it);
853 NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
854 const uint32_t identifier = GetIdentifierForUt(*it);
855
856 // Create the probe.
857 std::ostringstream probeName;
858 probeName << utId;
859 Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
860 probe->SetName(probeName.str());
861
862 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
863
864 // Connect the object to the probe.
865 if (probe->ConnectByObject("RxJitter", dev) && ConnectProbeToCollector(probe, identifier))
866 {
867 m_probes.insert(
868 std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
869
870 // Enable statistics-related tags and trace sources on the device.
871 dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
872 }
873 else
874 {
875 NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
876 << " at node ID " << (*it)->GetId() << " device #2");
877 }
878
879 } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
880
881 // Enable statistics-related tags on the transmitting device.
882 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
883 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
884 {
885 NetDeviceContainer devs = GetGwSatNetDevice(*it);
886
887 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
888 {
889 NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
890 (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
891 }
892 }
893
894} // end of `void DoInstallProbes ();`
895
896void
898{
899 NS_LOG_FUNCTION(this);
900
901 std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
902
903 for (it = m_probes.begin(); it != m_probes.end(); it++)
904 {
905 Ptr<Probe> probe = it->first;
906 Ptr<Node> node = it->second.first;
907 uint32_t identifier = it->second.second;
908
909 if (!DisconnectProbeFromCollector(probe, identifier))
910 {
911 NS_FATAL_ERROR("Error disconnecting trace file on handover");
912 }
913
914 identifier = GetIdentifierForUt(node);
915
916 if (!ConnectProbeToCollector(probe, identifier))
917 {
918 NS_FATAL_ERROR("Error connecting trace file on handover");
919 }
920
921 it->second.second = identifier;
922 }
923} // end of `void UpdateIdentifierOnProbes ();`
924
925// FORWARD LINK MAC-LEVEL /////////////////////////////////////////////////////
926
927NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdMacJitterHelper);
928
930 : SatStatsJitterHelper(satHelper)
931{
932 NS_LOG_FUNCTION(this << satHelper);
933}
934
936{
937 NS_LOG_FUNCTION(this);
938}
939
940TypeId // static
942{
943 static TypeId tid = TypeId("ns3::SatStatsFwdMacJitterHelper").SetParent<SatStatsJitterHelper>();
944 return tid;
945}
946
947void
949{
950 NS_LOG_FUNCTION(this);
951 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
952
953 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
954 {
955 const int32_t utId = GetUtId(*it);
956 NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
957 const uint32_t identifier = GetIdentifierForUt(*it);
958
959 // Create the probe.
960 std::ostringstream probeName;
961 probeName << utId;
962 Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
963 probe->SetName(probeName.str());
964
965 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
966 Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
967 NS_ASSERT(satDev != nullptr);
968 Ptr<SatMac> satMac = satDev->GetMac();
969 NS_ASSERT(satMac != nullptr);
970
971 // Connect the object to the probe.
972 if (probe->ConnectByObject("RxJitter", satMac) &&
973 ConnectProbeToCollector(probe, identifier))
974 {
975 m_probes.insert(
976 std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
977
978 // Enable statistics-related tags and trace sources on the device.
979 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
980 satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
981 }
982 else
983 {
984 NS_FATAL_ERROR("Error connecting to RxJitter trace source of satMac"
985 << " at node ID " << (*it)->GetId() << " device #2");
986 }
987
988 } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
989
990 // Enable statistics-related tags on the transmitting device.
991 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
992 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
993 {
994 NetDeviceContainer devs = GetGwSatNetDevice(*it);
995
996 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
997 {
998 Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
999 NS_ASSERT(satDev != nullptr);
1000 Ptr<SatMac> satMac = satDev->GetMac();
1001 NS_ASSERT(satMac != nullptr);
1002
1003 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1004 satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1005 }
1006 }
1007
1008} // end of `void DoInstallProbes ();`
1009
1010void
1012{
1013 NS_LOG_FUNCTION(this);
1014
1015 std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
1016
1017 for (it = m_probes.begin(); it != m_probes.end(); it++)
1018 {
1019 Ptr<Probe> probe = it->first;
1020 Ptr<Node> node = it->second.first;
1021 uint32_t identifier = it->second.second;
1022
1023 if (!DisconnectProbeFromCollector(probe, identifier))
1024 {
1025 NS_FATAL_ERROR("Error disconnecting trace file on handover");
1026 }
1027
1028 identifier = GetIdentifierForUt(node);
1029
1030 if (!ConnectProbeToCollector(probe, identifier))
1031 {
1032 NS_FATAL_ERROR("Error connecting trace file on handover");
1033 }
1034
1035 it->second.second = identifier;
1036 }
1037} // end of `void UpdateIdentifierOnProbes ();`
1038
1039// FORWARD LINK PHY-LEVEL /////////////////////////////////////////////////////
1040
1041NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdPhyJitterHelper);
1042
1044 : SatStatsJitterHelper(satHelper)
1045{
1046 NS_LOG_FUNCTION(this << satHelper);
1047}
1048
1050{
1051 NS_LOG_FUNCTION(this);
1052}
1053
1054TypeId // static
1056{
1057 static TypeId tid = TypeId("ns3::SatStatsFwdPhyJitterHelper").SetParent<SatStatsJitterHelper>();
1058 return tid;
1059}
1060
1061void
1063{
1064 NS_LOG_FUNCTION(this);
1065
1066 NodeContainer sats = Singleton<SatTopology>::Get()->GetOrbiterNodes();
1067
1068 for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
1069 {
1070 Ptr<NetDevice> dev = GetSatSatOrbiterNetDevice(*it);
1071 Ptr<SatOrbiterNetDevice> satOrbiterDev = dev->GetObject<SatOrbiterNetDevice>();
1072 NS_ASSERT(satOrbiterDev != nullptr);
1073 std::map<uint32_t, Ptr<SatPhy>> satOrbiterFeederPhys = satOrbiterDev->GetFeederPhy();
1074 Ptr<SatPhy> satPhy;
1075 for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterFeederPhys.begin();
1076 it2 != satOrbiterFeederPhys.end();
1077 ++it2)
1078 {
1079 satPhy = it2->second;
1080 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1081 }
1082 std::map<uint32_t, Ptr<SatPhy>> satOrbiterUserPhys = satOrbiterDev->GetUserPhy();
1083 for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterUserPhys.begin();
1084 it2 != satOrbiterUserPhys.end();
1085 ++it2)
1086 {
1087 satPhy = it2->second;
1088 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1089 }
1090 } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
1091
1092 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1093
1094 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1095 {
1096 const int32_t utId = GetUtId(*it);
1097 NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
1098 const uint32_t identifier = GetIdentifierForUt(*it);
1099
1100 // Create the probe.
1101 std::ostringstream probeName;
1102 probeName << utId;
1103 Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
1104 probe->SetName(probeName.str());
1105
1106 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1107 Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1108 NS_ASSERT(satDev != nullptr);
1109 Ptr<SatPhy> satPhy = satDev->GetPhy();
1110 NS_ASSERT(satPhy != nullptr);
1111
1112 // Connect the object to the probe.
1113 if (probe->ConnectByObject("RxJitter", satPhy) &&
1114 ConnectProbeToCollector(probe, identifier))
1115 {
1116 m_probes.insert(
1117 std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
1118
1119 // Enable statistics-related tags and trace sources on the device.
1120 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1121 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1122 }
1123 else
1124 {
1125 NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatPhy"
1126 << " at node ID " << (*it)->GetId() << " device #2");
1127 }
1128
1129 } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
1130
1131 // Enable statistics-related tags on the transmitting device.
1132 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1133 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1134 {
1135 NetDeviceContainer devs = GetGwSatNetDevice(*it);
1136
1137 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1138 {
1139 Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1140 NS_ASSERT(satDev != nullptr);
1141 Ptr<SatPhy> satPhy = satDev->GetPhy();
1142 NS_ASSERT(satPhy != nullptr);
1143
1144 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1145 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1146 }
1147 }
1148
1149} // end of `void DoInstallProbes ();`
1150
1151void
1153{
1154 NS_LOG_FUNCTION(this);
1155
1156 std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
1157
1158 for (it = m_probes.begin(); it != m_probes.end(); it++)
1159 {
1160 Ptr<Probe> probe = it->first;
1161 Ptr<Node> node = it->second.first;
1162 uint32_t identifier = it->second.second;
1163
1164 if (!DisconnectProbeFromCollector(probe, identifier))
1165 {
1166 NS_FATAL_ERROR("Error disconnecting trace file on handover");
1167 }
1168
1169 identifier = GetIdentifierForUt(node);
1170
1171 if (!ConnectProbeToCollector(probe, identifier))
1172 {
1173 NS_FATAL_ERROR("Error connecting trace file on handover");
1174 }
1175
1176 it->second.second = identifier;
1177 }
1178} // end of `void UpdateIdentifierOnProbes ();`
1179
1180// RETURN LINK APPLICATION-LEVEL //////////////////////////////////////////////
1181
1182NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnAppJitterHelper);
1183
1185 : SatStatsJitterHelper(satHelper)
1186{
1187 NS_LOG_FUNCTION(this << satHelper);
1188}
1189
1191{
1192 NS_LOG_FUNCTION(this);
1193}
1194
1195TypeId // static
1197{
1198 static TypeId tid = TypeId("ns3::SatStatsRtnAppJitterHelper").SetParent<SatStatsJitterHelper>();
1199 return tid;
1200}
1201
1202void
1204{
1205 NS_LOG_FUNCTION(this);
1206
1207 NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtUserNodes();
1208 for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
1209 {
1210 // Create a map of UT user addresses and identifiers.
1212
1213 /*
1214 * Some sender applications might need a special attribute to be enabled
1215 * before jitter statistics can be computed. We enable it here.
1216 */
1217 for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1218 {
1219 Ptr<Application> app = (*it)->GetApplication(i);
1220
1221 if (!app->SetAttributeFailSafe("EnableStatisticsTags", BooleanValue(true)))
1222 {
1223 NS_LOG_WARN(this << " node ID " << (*it)->GetId() << " application #" << i
1224 << " might not produce the required tags"
1225 << " in the transmitted packets,"
1226 << " thus preventing jitter statistics"
1227 << " from this sender application");
1228 }
1229
1230 } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1231
1232 } // end of `for (NodeContainer::Iterator it: utUsers)`
1233
1234 // Connect to trace sources at GW user node's applications.
1235
1236 NodeContainer gwUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
1237 Callback<void, const Time&, const Address&> rxJitterCallback =
1238 MakeCallback(&SatStatsRtnAppJitterHelper::Ipv4Callback, this);
1239 Callback<void, Ptr<const Packet>, const Address&> rxCallback =
1240 MakeCallback(&SatStatsRtnAppJitterHelper::RxCallback, this);
1241
1242 for (NodeContainer::Iterator it = gwUsers.Begin(); it != gwUsers.End(); ++it)
1243 {
1244 for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1245 {
1246 Ptr<Application> app = (*it)->GetApplication(i);
1247 bool isConnected = false;
1248
1249 /*
1250 * Some applications support RxJitter trace sources, and some other
1251 * applications support Rx trace sources. Below we support both ways.
1252 */
1253 if (app->GetInstanceTypeId().LookupTraceSourceByName("RxJitter") != nullptr)
1254 {
1255 isConnected = app->TraceConnectWithoutContext("RxJitter", rxJitterCallback);
1256 }
1257 else if (app->GetInstanceTypeId().LookupTraceSourceByName("Rx") != nullptr)
1258 {
1259 isConnected = app->TraceConnectWithoutContext("Rx", rxCallback);
1260 }
1261
1262 if (isConnected)
1263 {
1264 NS_LOG_INFO(this << " successfully connected" << " with node ID " << (*it)->GetId()
1265 << " application #" << i);
1266 }
1267 else
1268 {
1269 /*
1270 * We're being tolerant here by only logging a warning, because
1271 * not every kind of Application is equipped with the expected
1272 * RxJitter or Rx trace source.
1273 */
1274 NS_LOG_WARN(this << " unable to connect" << " with node ID " << (*it)->GetId()
1275 << " application #" << i);
1276 }
1277
1278 } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1279
1280 } // end of `for (NodeContainer::Iterator it: gwUsers)`
1281
1282} // end of `void DoInstallProbes ();`
1283
1284void
1285SatStatsRtnAppJitterHelper::RxCallback(Ptr<const Packet> packet, const Address& from)
1286{
1287 TrafficTimeTag timeTag;
1288 if (packet->PeekPacketTag(timeTag))
1289 {
1290 NS_LOG_DEBUG(this << " contains a TrafficTimeTag tag");
1291 const Time delay = Simulator::Now() - timeTag.GetSenderTimestamp();
1292 const Address identifier = InetSocketAddress::ConvertFrom(from).GetIpv4();
1293 std::map<const Address, Time>::iterator it = m_previousDelayMap.find(identifier);
1294 if (it != m_previousDelayMap.end())
1295 {
1296 Time previousDelay = it->second;
1297 Time jitter = Abs(delay - previousDelay);
1298 Ipv4Callback(jitter, from);
1299 }
1300 m_previousDelayMap[identifier] = delay;
1301 }
1302 else
1303 {
1304 NS_LOG_WARN(this << " discarding a packet of " << packet->GetSize()
1305 << " from statistics collection"
1306 << " because it does not contain any TrafficTimeTag");
1307 }
1308} // end of `void RxCallback (Ptr<const Packet>, const Address);`
1309
1310void
1311SatStatsRtnAppJitterHelper::Ipv4Callback(const Time& jitter, const Address& from)
1312{
1313 // NS_LOG_FUNCTION (this << Time.GetSeconds () << from);
1314
1315 if (InetSocketAddress::IsMatchingType(from))
1316 {
1317 // Determine the identifier associated with the sender address.
1318 const Address ipv4Addr = InetSocketAddress::ConvertFrom(from).GetIpv4();
1319 std::map<const Address, uint32_t>::const_iterator it1 = m_identifierMap.find(ipv4Addr);
1320
1321 if (it1 == m_identifierMap.end())
1322 {
1323 NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.GetSeconds()
1324 << " from statistics collection because of"
1325 << " unknown sender IPV4 address " << ipv4Addr);
1326 }
1327 else
1328 {
1329 PassSampleToCollector(jitter, it1->second);
1330 }
1331 }
1332 else
1333 {
1334 NS_LOG_WARN(this << " discarding a packet jitter of " << jitter.GetSeconds()
1335 << " from statistics collection" << " because it comes from sender "
1336 << from << " without valid InetSocketAddress");
1337 }
1338}
1339
1340void
1342{
1343 NS_LOG_FUNCTION(this << utUserNode->GetId());
1344
1345 Ptr<Ipv4> ipv4 = utUserNode->GetObject<Ipv4>();
1346
1347 if (ipv4 == nullptr)
1348 {
1349 NS_LOG_INFO(this << " Node " << utUserNode->GetId() << " does not support IPv4 protocol");
1350 }
1351 else if (ipv4->GetNInterfaces() >= 2)
1352 {
1353 const uint32_t identifier = GetIdentifierForUtUser(utUserNode);
1354
1355 /*
1356 * Assuming that #0 is for loopback interface and #1 is for subscriber
1357 * network interface.
1358 */
1359 for (uint32_t i = 0; i < ipv4->GetNAddresses(1); i++)
1360 {
1361 const Address addr = ipv4->GetAddress(1, i).GetLocal();
1362 m_identifierMap[addr] = identifier;
1363 NS_LOG_INFO(this << " associated address " << addr << " with identifier "
1364 << identifier);
1365 }
1366 }
1367 else
1368 {
1369 NS_LOG_WARN(this << " Node " << utUserNode->GetId() << " is not a valid UT user");
1370 }
1371}
1372
1373// RETURN LINK DEVICE-LEVEL ///////////////////////////////////////////////////
1374
1375NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnDevJitterHelper);
1376
1378 : SatStatsJitterHelper(satHelper)
1379{
1380 NS_LOG_FUNCTION(this << satHelper);
1381}
1382
1384{
1385 NS_LOG_FUNCTION(this);
1386}
1387
1388TypeId // static
1390{
1391 static TypeId tid = TypeId("ns3::SatStatsRtnDevJitterHelper").SetParent<SatStatsJitterHelper>();
1392 return tid;
1393}
1394
1395void
1397{
1398 NS_LOG_FUNCTION(this);
1399
1400 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1401 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1402 {
1403 // Create a map of UT addresses and identifiers.
1405
1406 // Enable statistics-related tags and trace sources on the device.
1407 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1408 dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1409 }
1410
1411 // Connect to trace sources at GW nodes.
1412
1413 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1414 Callback<void, const Time&, const Address&> callback =
1416
1417 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1418 {
1419 NetDeviceContainer devs = GetGwSatNetDevice(*it);
1420
1421 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1422 {
1423 NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
1424
1425 if ((*itDev)->TraceConnectWithoutContext("RxJitter", callback))
1426 {
1427 NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1428 << " device #" << (*itDev)->GetIfIndex());
1429
1430 // Enable statistics-related tags and trace sources on the device.
1431 (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1432 }
1433 else
1434 {
1435 NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
1436 << " at node ID " << (*it)->GetId() << " device #"
1437 << (*itDev)->GetIfIndex());
1438 }
1439
1440 } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1441
1442 } // end of `for (NodeContainer::Iterator it = gws)`
1443
1444} // end of `void DoInstallProbes ();`
1445
1446// RETURN LINK MAC-LEVEL //////////////////////////////////////////////////////
1447
1448NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnMacJitterHelper);
1449
1451 : SatStatsJitterHelper(satHelper)
1452{
1453 NS_LOG_FUNCTION(this << satHelper);
1454}
1455
1457{
1458 NS_LOG_FUNCTION(this);
1459}
1460
1461TypeId // static
1463{
1464 static TypeId tid = TypeId("ns3::SatStatsRtnMacJitterHelper").SetParent<SatStatsJitterHelper>();
1465 return tid;
1466}
1467
1468void
1470{
1471 NS_LOG_FUNCTION(this);
1472
1473 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1474 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1475 {
1476 // Create a map of UT addresses and identifiers.
1478
1479 // Enable statistics-related tags and trace sources on the device.
1480 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1481 Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1482 NS_ASSERT(satDev != nullptr);
1483 Ptr<SatMac> satMac = satDev->GetMac();
1484 NS_ASSERT(satMac != nullptr);
1485 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1486 satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1487 }
1488
1489 // Connect to trace sources at GW nodes.
1490
1491 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1492 Callback<void, const Time&, const Address&> callback =
1494
1495 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1496 {
1497 NetDeviceContainer devs = GetGwSatNetDevice(*it);
1498
1499 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1500 {
1501 Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1502 NS_ASSERT(satDev != nullptr);
1503 Ptr<SatMac> satMac = satDev->GetMac();
1504 NS_ASSERT(satMac != nullptr);
1505
1506 // Connect the object to the probe.
1507 if (satMac->TraceConnectWithoutContext("RxJitter", callback))
1508 {
1509 NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1510 << " device #" << satDev->GetIfIndex());
1511
1512 // Enable statistics-related tags and trace sources on the device.
1513 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1514 satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1515 }
1516 else
1517 {
1518 NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
1519 << " at node ID " << (*it)->GetId() << " device #"
1520 << satDev->GetIfIndex());
1521 }
1522
1523 } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1524
1525 } // end of `for (NodeContainer::Iterator it = gws)`
1526
1527} // end of `void DoInstallProbes ();`
1528
1529// RETURN LINK PHY-LEVEL //////////////////////////////////////////////////////
1530
1531NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnPhyJitterHelper);
1532
1534 : SatStatsJitterHelper(satHelper)
1535{
1536 NS_LOG_FUNCTION(this << satHelper);
1537}
1538
1540{
1541 NS_LOG_FUNCTION(this);
1542}
1543
1544TypeId // static
1546{
1547 static TypeId tid = TypeId("ns3::SatStatsRtnPhyJitterHelper").SetParent<SatStatsJitterHelper>();
1548 return tid;
1549}
1550
1551void
1553{
1554 NS_LOG_FUNCTION(this);
1555
1556 NodeContainer sats = Singleton<SatTopology>::Get()->GetOrbiterNodes();
1557
1558 for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
1559 {
1560 Ptr<NetDevice> dev = GetSatSatOrbiterNetDevice(*it);
1561 Ptr<SatOrbiterNetDevice> satOrbiterDev = dev->GetObject<SatOrbiterNetDevice>();
1562 NS_ASSERT(satOrbiterDev != nullptr);
1563 std::map<uint32_t, Ptr<SatPhy>> satOrbiterFeederPhys = satOrbiterDev->GetFeederPhy();
1564 Ptr<SatPhy> satPhy;
1565 for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterFeederPhys.begin();
1566 it2 != satOrbiterFeederPhys.end();
1567 ++it2)
1568 {
1569 satPhy = it2->second;
1570 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1571 }
1572 std::map<uint32_t, Ptr<SatPhy>> satOrbiterUserPhys = satOrbiterDev->GetUserPhy();
1573 for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterUserPhys.begin();
1574 it2 != satOrbiterUserPhys.end();
1575 ++it2)
1576 {
1577 satPhy = it2->second;
1578 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1579 }
1580 } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
1581
1582 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1583 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1584 {
1585 // Create a map of UT addresses and identifiers.
1587
1588 // Enable statistics-related tags and trace sources on the device.
1589 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1590 Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1591 NS_ASSERT(satDev != nullptr);
1592 Ptr<SatPhy> satPhy = satDev->GetPhy();
1593 NS_ASSERT(satPhy != nullptr);
1594 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1595 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1596 }
1597
1598 // Connect to trace sources at GW nodes.
1599
1600 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1601 Callback<void, const Time&, const Address&> callback =
1603
1604 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1605 {
1606 NetDeviceContainer devs = GetGwSatNetDevice(*it);
1607
1608 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1609 {
1610 Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1611 NS_ASSERT(satDev != nullptr);
1612 Ptr<SatPhy> satPhy = satDev->GetPhy();
1613 NS_ASSERT(satPhy != nullptr);
1614
1615 // Connect the object to the probe.
1616 if (satPhy->TraceConnectWithoutContext("RxJitter", callback))
1617 {
1618 NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1619 << " device #" << satDev->GetIfIndex());
1620
1621 // Enable statistics-related tags and trace sources on the device.
1622 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1623 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1624 }
1625 else
1626 {
1627 NS_FATAL_ERROR("Error connecting to RxJitter trace source of SatNetDevice"
1628 << " at node ID " << (*it)->GetId() << " device #"
1629 << satDev->GetIfIndex());
1630 }
1631
1632 } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1633
1634 } // end of `for (NodeContainer::Iterator it = gws)`
1635
1636} // end of `void DoInstallProbes ();`
1637
1638} // 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.
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)
SatStatsHelper(Ptr< const SatHelper > satHelper)
Creates a new helper instance.
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.
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.