Loading...
Searching...
No Matches
satellite-stats-delay-helper.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2014 Magister Solutions
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Budiarto Herman <budiarto.herman@magister.fi>
19 *
20 */
21
23
24#include "ns3/application-delay-probe.h"
25#include "ns3/application.h"
26#include "ns3/boolean.h"
27#include "ns3/callback.h"
28#include "ns3/data-collection-object.h"
29#include "ns3/distribution-collector.h"
30#include "ns3/enum.h"
31#include "ns3/inet-socket-address.h"
32#include "ns3/ipv4.h"
33#include "ns3/log.h"
34#include "ns3/mac48-address.h"
35#include "ns3/magister-gnuplot-aggregator.h"
36#include "ns3/multi-file-aggregator.h"
37#include "ns3/net-device.h"
38#include "ns3/node-container.h"
39#include "ns3/nstime.h"
40#include "ns3/probe.h"
41#include "ns3/satellite-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("SatStatsDelayHelper");
61
62namespace ns3
63{
64
65NS_OBJECT_ENSURE_REGISTERED(SatStatsDelayHelper);
66
67SatStatsDelayHelper::SatStatsDelayHelper(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::SatStatsDelayHelper")
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(&SatStatsDelayHelper::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("delay_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("delay_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("delay_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("delay_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 delay (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 delay (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 delay (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("SatStatsDelayHelper - 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
422SatStatsDelayHelper::RxDelayCallback(const Time& delay, const Address& from)
423{
424 // NS_LOG_FUNCTION (this << delay.GetSeconds () << from);
425
426 if (from.IsInvalid())
427 {
428 NS_LOG_WARN(this << " discarding a packet delay of " << delay.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(delay, it->second);
439 }
440 else
441 {
442 NS_LOG_WARN(this << " discarding a packet delay of " << delay.GetSeconds()
443 << " from statistics collection because of"
444 << " unknown sender address " << from);
445 }
446 }
447}
448
449bool
450SatStatsDelayHelper::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
516SatStatsDelayHelper::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
582SatStatsDelayHelper::PassSampleToCollector(const Time& delay, uint32_t identifier)
583{
584 // NS_LOG_FUNCTION (this << delay.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, delay.GetSeconds());
596 break;
597 }
598
601 Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
602 NS_ASSERT(c != nullptr);
603 c->TraceSinkDouble(0.0, delay.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, delay.GetSeconds());
618 }
619 else
620 {
621 Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
622 NS_ASSERT(c != nullptr);
623 c->TraceSinkDouble(0.0, delay.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(SatStatsFwdAppDelayHelper);
639
641 : SatStatsDelayHelper(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::SatStatsFwdAppDelayHelper").SetParent<SatStatsDelayHelper>();
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 RxDelay trace sources, and some other
677 * applications support Rx trace sources. Below we support both ways.
678 */
679 if (app->GetInstanceTypeId().LookupTraceSourceByName("RxDelay") != nullptr)
680 {
681 NS_LOG_INFO(this << " attempt to connect using RxDelay");
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("RxDelay", 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(&SatStatsFwdAppDelayHelper::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 * RxDelay 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 delay 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 delay 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 // static
752SatStatsFwdAppDelayHelper::RxCallback(Ptr<SatStatsFwdAppDelayHelper> helper,
753 uint32_t identifier,
754 Ptr<const Packet> packet,
755 const Address& from)
756{
757 NS_LOG_FUNCTION(helper << identifier << packet << packet->GetSize() << from);
758
759 // bool isTagged = false;
760 // ByteTagIterator it = packet->GetByteTagIterator ();
761 //
762 // while (!isTagged && it.HasNext ())
763 // {
764 // ByteTagIterator::Item item = it.Next ();
765 //
766 // if (item.GetTypeId () == TrafficTimeTag::GetTypeId ())
767 // {
768 // NS_LOG_DEBUG ("Contains a TrafficTimeTag tag:"
769 // << " start=" << item.GetStart ()
770 // << " end=" << item.GetEnd ());
771 // TrafficTimeTag timeTag;
772 // item.GetTag (timeTag);
773 // const Time delay = Simulator::Now () - timeTag.GetSenderTimestamp ();
774 // helper->PassSampleToCollector (delay, identifier);
775 // isTagged = true; // this will exit the while loop.
776 // }
777 // }
778 //
779 // if (!isTagged)
780 // {
781 // NS_LOG_WARN ("Discarding a packet of " << packet->GetSize ()
782 // << " from statistics collection"
783 // << " because it does not contain any TrafficTimeTag");
784 // }
785
786 TrafficTimeTag timeTag;
787 if (packet->PeekPacketTag(timeTag))
788 {
789 NS_LOG_DEBUG("Contains a TrafficTimeTag tag");
790 const Time delay = Simulator::Now() - timeTag.GetSenderTimestamp();
791 helper->PassSampleToCollector(delay, identifier);
792 }
793 else
794 {
795 NS_LOG_WARN("Discarding a packet of " << packet->GetSize() << " from statistics collection"
796 << " because it does not contain any TrafficTimeTag");
797 }
798}
799
800void
802{
803 NS_LOG_FUNCTION(this);
804
805 std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
806
807 for (it = m_probes.begin(); it != m_probes.end(); it++)
808 {
809 Ptr<Probe> probe = it->first;
810 Ptr<Node> node = it->second.first;
811 uint32_t identifier = it->second.second;
812
813 if (!DisconnectProbeFromCollector(probe, identifier))
814 {
815 NS_FATAL_ERROR("Error disconnecting trace file on handover");
816 }
817
818 identifier = GetIdentifierForUtUser(node);
819
820 if (!ConnectProbeToCollector(probe, identifier))
821 {
822 NS_FATAL_ERROR("Error connecting trace file on handover");
823 }
824
825 it->second.second = identifier;
826 }
827} // end of `void UpdateIdentifierOnProbes ();`
828
829// FORWARD LINK DEVICE-LEVEL //////////////////////////////////////////////////
830
831NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdDevDelayHelper);
832
834 : SatStatsDelayHelper(satHelper)
835{
836 NS_LOG_FUNCTION(this << satHelper);
837}
838
840{
841 NS_LOG_FUNCTION(this);
842}
843
844TypeId // static
846{
847 static TypeId tid = TypeId("ns3::SatStatsFwdDevDelayHelper").SetParent<SatStatsDelayHelper>();
848 return tid;
849}
850
851void
853{
854 NS_LOG_FUNCTION(this);
855 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
856
857 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
858 {
859 const int32_t utId = GetUtId(*it);
860 NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
861 const uint32_t identifier = GetIdentifierForUt(*it);
862
863 // Create the probe.
864 std::ostringstream probeName;
865 probeName << utId;
866 Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
867 probe->SetName(probeName.str());
868
869 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
870
871 // Connect the object to the probe.
872 if (probe->ConnectByObject("RxDelay", dev) && ConnectProbeToCollector(probe, identifier))
873 {
874 m_probes.insert(
875 std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
876
877 // Enable statistics-related tags and trace sources on the device.
878 dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
879 }
880 else
881 {
882 NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatNetDevice"
883 << " at node ID " << (*it)->GetId() << " device #2");
884 }
885
886 } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
887
888 // Enable statistics-related tags on the transmitting device.
889 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
890 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
891 {
892 NetDeviceContainer devs = GetGwSatNetDevice(*it);
893
894 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
895 {
896 NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
897 (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
898 }
899 }
900
901} // end of `void DoInstallProbes ();`
902
903void
905{
906 NS_LOG_FUNCTION(this);
907
908 std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
909
910 for (it = m_probes.begin(); it != m_probes.end(); it++)
911 {
912 Ptr<Probe> probe = it->first;
913 Ptr<Node> node = it->second.first;
914 uint32_t identifier = it->second.second;
915
916 if (!DisconnectProbeFromCollector(probe, identifier))
917 {
918 NS_FATAL_ERROR("Error disconnecting trace file on handover");
919 }
920
921 identifier = GetIdentifierForUt(node);
922
923 if (!ConnectProbeToCollector(probe, identifier))
924 {
925 NS_FATAL_ERROR("Error connecting trace file on handover");
926 }
927
928 it->second.second = identifier;
929 }
930} // end of `void UpdateIdentifierOnProbes ();`
931
932// FORWARD LINK MAC-LEVEL /////////////////////////////////////////////////////
933
934NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdMacDelayHelper);
935
937 : SatStatsDelayHelper(satHelper)
938{
939 NS_LOG_FUNCTION(this << satHelper);
940}
941
943{
944 NS_LOG_FUNCTION(this);
945}
946
947TypeId // static
949{
950 static TypeId tid = TypeId("ns3::SatStatsFwdMacDelayHelper").SetParent<SatStatsDelayHelper>();
951 return tid;
952}
953
954void
956{
957 NS_LOG_FUNCTION(this);
958 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
959
960 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
961 {
962 const int32_t utId = GetUtId(*it);
963 NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
964 const uint32_t identifier = GetIdentifierForUt(*it);
965
966 // Create the probe.
967 std::ostringstream probeName;
968 probeName << utId;
969 Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
970 probe->SetName(probeName.str());
971
972 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
973 Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
974 NS_ASSERT(satDev != nullptr);
975 Ptr<SatMac> satMac = satDev->GetMac();
976 NS_ASSERT(satMac != nullptr);
977
978 // Connect the object to the probe.
979 if (probe->ConnectByObject("RxDelay", satMac) && ConnectProbeToCollector(probe, identifier))
980 {
981 m_probes.insert(
982 std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
983
984 // Enable statistics-related tags and trace sources on the device.
985 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
986 satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
987 }
988 else
989 {
990 NS_FATAL_ERROR("Error connecting to RxDelay trace source of satMac"
991 << " at node ID " << (*it)->GetId() << " device #2");
992 }
993
994 } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
995
996 // Enable statistics-related tags on the transmitting device.
997 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
998 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
999 {
1000 NetDeviceContainer devs = GetGwSatNetDevice(*it);
1001
1002 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1003 {
1004 Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1005 NS_ASSERT(satDev != nullptr);
1006 Ptr<SatMac> satMac = satDev->GetMac();
1007 NS_ASSERT(satMac != nullptr);
1008
1009 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1010 satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1011 }
1012 }
1013
1014} // end of `void DoInstallProbes ();`
1015
1016void
1018{
1019 NS_LOG_FUNCTION(this);
1020
1021 std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
1022
1023 for (it = m_probes.begin(); it != m_probes.end(); it++)
1024 {
1025 Ptr<Probe> probe = it->first;
1026 Ptr<Node> node = it->second.first;
1027 uint32_t identifier = it->second.second;
1028
1029 if (!DisconnectProbeFromCollector(probe, identifier))
1030 {
1031 NS_FATAL_ERROR("Error disconnecting trace file on handover");
1032 }
1033
1034 identifier = GetIdentifierForUt(node);
1035
1036 if (!ConnectProbeToCollector(probe, identifier))
1037 {
1038 NS_FATAL_ERROR("Error connecting trace file on handover");
1039 }
1040
1041 it->second.second = identifier;
1042 }
1043} // end of `void UpdateIdentifierOnProbes ();`
1044
1045// FORWARD LINK PHY-LEVEL /////////////////////////////////////////////////////
1046
1047NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdPhyDelayHelper);
1048
1050 : SatStatsDelayHelper(satHelper)
1051{
1052 NS_LOG_FUNCTION(this << satHelper);
1053}
1054
1056{
1057 NS_LOG_FUNCTION(this);
1058}
1059
1060TypeId // static
1062{
1063 static TypeId tid = TypeId("ns3::SatStatsFwdPhyDelayHelper").SetParent<SatStatsDelayHelper>();
1064 return tid;
1065}
1066
1067void
1069{
1070 NS_LOG_FUNCTION(this);
1071
1072 NodeContainer sats = Singleton<SatTopology>::Get()->GetOrbiterNodes();
1073
1074 for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
1075 {
1076 Ptr<NetDevice> dev = GetSatSatOrbiterNetDevice(*it);
1077 Ptr<SatOrbiterNetDevice> satOrbiterDev = dev->GetObject<SatOrbiterNetDevice>();
1078 NS_ASSERT(satOrbiterDev != nullptr);
1079 std::map<uint32_t, Ptr<SatPhy>> satOrbiterFeederPhys = satOrbiterDev->GetFeederPhy();
1080 Ptr<SatPhy> satPhy;
1081 for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterFeederPhys.begin();
1082 it2 != satOrbiterFeederPhys.end();
1083 ++it2)
1084 {
1085 satPhy = it2->second;
1086 NS_ASSERT(satPhy != nullptr);
1087 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1088 }
1089 std::map<uint32_t, Ptr<SatPhy>> satOrbiterUserPhys = satOrbiterDev->GetUserPhy();
1090 for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterUserPhys.begin();
1091 it2 != satOrbiterUserPhys.end();
1092 ++it2)
1093 {
1094 satPhy = it2->second;
1095 NS_ASSERT(satPhy != nullptr);
1096 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1097 }
1098 } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
1099
1100 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1101
1102 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1103 {
1104 const int32_t utId = GetUtId(*it);
1105 NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
1106 const uint32_t identifier = GetIdentifierForUt(*it);
1107
1108 // Create the probe.
1109 std::ostringstream probeName;
1110 probeName << utId;
1111 Ptr<ApplicationDelayProbe> probe = CreateObject<ApplicationDelayProbe>();
1112 probe->SetName(probeName.str());
1113
1114 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1115 Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1116 NS_ASSERT(satDev != nullptr);
1117 Ptr<SatPhy> satPhy = satDev->GetPhy();
1118 NS_ASSERT(satPhy != nullptr);
1119
1120 // Connect the object to the probe.
1121 if (probe->ConnectByObject("RxDelay", satPhy) && ConnectProbeToCollector(probe, identifier))
1122 {
1123 m_probes.insert(
1124 std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
1125
1126 // Enable statistics-related tags and trace sources on the device.
1127 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1128 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1129 }
1130 else
1131 {
1132 NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatPhy"
1133 << " at node ID " << (*it)->GetId() << " device #2");
1134 }
1135
1136 } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
1137
1138 // Enable statistics-related tags on the transmitting device.
1139 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1140 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1141 {
1142 NetDeviceContainer devs = GetGwSatNetDevice(*it);
1143
1144 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1145 {
1146 Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1147 NS_ASSERT(satDev != nullptr);
1148 Ptr<SatPhy> satPhy = satDev->GetPhy();
1149 NS_ASSERT(satPhy != nullptr);
1150
1151 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1152 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1153 }
1154 }
1155
1156} // end of `void DoInstallProbes ();`
1157
1158void
1160{
1161 NS_LOG_FUNCTION(this);
1162
1163 std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
1164
1165 for (it = m_probes.begin(); it != m_probes.end(); it++)
1166 {
1167 Ptr<Probe> probe = it->first;
1168 Ptr<Node> node = it->second.first;
1169 uint32_t identifier = it->second.second;
1170
1171 if (!DisconnectProbeFromCollector(probe, identifier))
1172 {
1173 NS_FATAL_ERROR("Error disconnecting trace file on handover");
1174 }
1175
1176 identifier = GetIdentifierForUt(node);
1177
1178 if (!ConnectProbeToCollector(probe, identifier))
1179 {
1180 NS_FATAL_ERROR("Error connecting trace file on handover");
1181 }
1182
1183 it->second.second = identifier;
1184 }
1185} // end of `void UpdateIdentifierOnProbes ();`
1186
1187// RETURN LINK APPLICATION-LEVEL //////////////////////////////////////////////
1188
1189NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnAppDelayHelper);
1190
1192 : SatStatsDelayHelper(satHelper)
1193{
1194 NS_LOG_FUNCTION(this << satHelper);
1195}
1196
1198{
1199 NS_LOG_FUNCTION(this);
1200}
1201
1202TypeId // static
1204{
1205 static TypeId tid = TypeId("ns3::SatStatsRtnAppDelayHelper").SetParent<SatStatsDelayHelper>();
1206 return tid;
1207}
1208
1209void
1211{
1212 NS_LOG_FUNCTION(this);
1213
1214 NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtUserNodes();
1215 for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
1216 {
1217 // Create a map of UT user addresses and identifiers.
1219
1220 /*
1221 * Some sender applications might need a special attribute to be enabled
1222 * before delay statistics can be computed. We enable it here.
1223 */
1224 for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1225 {
1226 Ptr<Application> app = (*it)->GetApplication(i);
1227
1228 if (!app->SetAttributeFailSafe("EnableStatisticsTags", BooleanValue(true)))
1229 {
1230 NS_LOG_WARN(
1231 this << " node ID " << (*it)->GetId() << " application #" << i
1232 << " might not produce the required tags" << " in the transmitted packets,"
1233 << " thus preventing delay statistics" << " from this sender application");
1234 }
1235
1236 } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1237
1238 } // end of `for (NodeContainer::Iterator it: utUsers)`
1239
1240 // Connect to trace sources at GW user node's applications.
1241
1242 NodeContainer gwUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
1243 Callback<void, const Time&, const Address&> rxDelayCallback =
1244 MakeCallback(&SatStatsRtnAppDelayHelper::Ipv4Callback, this);
1245 Callback<void, Ptr<const Packet>, const Address&> rxCallback =
1246 MakeCallback(&SatStatsRtnAppDelayHelper::RxCallback, this);
1247
1248 for (NodeContainer::Iterator it = gwUsers.Begin(); it != gwUsers.End(); ++it)
1249 {
1250 for (uint32_t i = 0; i < (*it)->GetNApplications(); i++)
1251 {
1252 Ptr<Application> app = (*it)->GetApplication(i);
1253 bool isConnected = false;
1254
1255 /*
1256 * Some applications support RxDelay trace sources, and some other
1257 * applications support Rx trace sources. Below we support both ways.
1258 */
1259 if (app->GetInstanceTypeId().LookupTraceSourceByName("RxDelay") != nullptr)
1260 {
1261 isConnected = app->TraceConnectWithoutContext("RxDelay", rxDelayCallback);
1262 }
1263 else if (app->GetInstanceTypeId().LookupTraceSourceByName("Rx") != nullptr)
1264 {
1265 isConnected = app->TraceConnectWithoutContext("Rx", rxCallback);
1266 }
1267
1268 if (isConnected)
1269 {
1270 NS_LOG_INFO(this << " successfully connected" << " with node ID " << (*it)->GetId()
1271 << " application #" << i);
1272 }
1273 else
1274 {
1275 /*
1276 * We're being tolerant here by only logging a warning, because
1277 * not every kind of Application is equipped with the expected
1278 * RxDelay or Rx trace source.
1279 */
1280 NS_LOG_WARN(this << " unable to connect" << " with node ID " << (*it)->GetId()
1281 << " application #" << i);
1282 }
1283
1284 } // end of `for (i = 0; i < (*it)->GetNApplications (); i++)`
1285
1286 } // end of `for (NodeContainer::Iterator it: gwUsers)`
1287
1288} // end of `void DoInstallProbes ();`
1289
1290void
1291SatStatsRtnAppDelayHelper::RxCallback(Ptr<const Packet> packet, const Address& from)
1292{
1293 // NS_LOG_FUNCTION (this << packet << packet->GetSize () << from);
1294
1295 // bool isTagged = false;
1296 // ByteTagIterator it = packet->GetByteTagIterator ();
1297 //
1298 // while (!isTagged && it.HasNext ())
1299 // {
1300 // ByteTagIterator::Item item = it.Next ();
1301 //
1302 // if (item.GetTypeId () == TrafficTimeTag::GetTypeId ())
1303 // {
1304 // NS_LOG_DEBUG ("Contains a TrafficTimeTag tag:"
1305 // << " start=" << item.GetStart ()
1306 // << " end=" << item.GetEnd ());
1307 // TrafficTimeTag timeTag;
1308 // item.GetTag (timeTag);
1309 // const Time delay = Simulator::Now () - timeTag.GetSenderTimestamp ();
1310 // helper->PassSampleToCollector (delay, identifier);
1311 // isTagged = true; // this will exit the while loop.
1312 // }
1313 // }
1314 //
1315 // if (!isTagged)
1316 // {
1317 // NS_LOG_WARN ("Discarding a packet of " << packet->GetSize ()
1318 // << " from statistics collection"
1319 // << " because it does not contain any TrafficTimeTag");
1320 // }
1321
1322 TrafficTimeTag timeTag;
1323 if (packet->PeekPacketTag(timeTag))
1324 {
1325 NS_LOG_DEBUG(this << " contains a TrafficTimeTag tag");
1326 Ipv4Callback(Simulator::Now() - timeTag.GetSenderTimestamp(), from);
1327 }
1328 else
1329 {
1330 NS_LOG_WARN(this << " discarding a packet of " << packet->GetSize()
1331 << " from statistics collection"
1332 << " because it does not contain any TrafficTimeTag");
1333 }
1334
1335} // end of `void RxCallback (Ptr<const Packet>, const Address);`
1336
1337void
1338SatStatsRtnAppDelayHelper::Ipv4Callback(const Time& delay, const Address& from)
1339{
1340 // NS_LOG_FUNCTION (this << Time.GetSeconds () << from);
1341
1342 if (InetSocketAddress::IsMatchingType(from))
1343 {
1344 // Determine the identifier associated with the sender address.
1345 const Address ipv4Addr = InetSocketAddress::ConvertFrom(from).GetIpv4();
1346 std::map<const Address, uint32_t>::const_iterator it1 = m_identifierMap.find(ipv4Addr);
1347
1348 if (it1 == m_identifierMap.end())
1349 {
1350 NS_LOG_WARN(this << " discarding a packet delay of " << delay.GetSeconds()
1351 << " from statistics collection because of"
1352 << " unknown sender IPV4 address " << ipv4Addr);
1353 }
1354 else
1355 {
1356 PassSampleToCollector(delay, it1->second);
1357 }
1358 }
1359 else
1360 {
1361 NS_LOG_WARN(this << " discarding a packet delay of " << delay.GetSeconds()
1362 << " from statistics collection" << " because it comes from sender "
1363 << from << " without valid InetSocketAddress");
1364 }
1365}
1366
1367void
1369{
1370 NS_LOG_FUNCTION(this << utUserNode->GetId());
1371
1372 Ptr<Ipv4> ipv4 = utUserNode->GetObject<Ipv4>();
1373
1374 if (ipv4 == nullptr)
1375 {
1376 NS_LOG_INFO(this << " Node " << utUserNode->GetId() << " does not support IPv4 protocol");
1377 }
1378 else if (ipv4->GetNInterfaces() >= 2)
1379 {
1380 const uint32_t identifier = GetIdentifierForUtUser(utUserNode);
1381
1382 /*
1383 * Assuming that #0 is for loopback interface and #1 is for subscriber
1384 * network interface.
1385 */
1386 for (uint32_t i = 0; i < ipv4->GetNAddresses(1); i++)
1387 {
1388 const Address addr = ipv4->GetAddress(1, i).GetLocal();
1389 m_identifierMap[addr] = identifier;
1390 NS_LOG_INFO(this << " associated address " << addr << " with identifier "
1391 << identifier);
1392 }
1393 }
1394 else
1395 {
1396 NS_LOG_WARN(this << " Node " << utUserNode->GetId() << " is not a valid UT user");
1397 }
1398}
1399
1400// RETURN LINK DEVICE-LEVEL ///////////////////////////////////////////////////
1401
1402NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnDevDelayHelper);
1403
1405 : SatStatsDelayHelper(satHelper)
1406{
1407 NS_LOG_FUNCTION(this << satHelper);
1408}
1409
1411{
1412 NS_LOG_FUNCTION(this);
1413}
1414
1415TypeId // static
1417{
1418 static TypeId tid = TypeId("ns3::SatStatsRtnDevDelayHelper").SetParent<SatStatsDelayHelper>();
1419 return tid;
1420}
1421
1422void
1424{
1425 NS_LOG_FUNCTION(this);
1426
1427 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1428 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1429 {
1430 // Create a map of UT addresses and identifiers.
1432
1433 // Enable statistics-related tags and trace sources on the device.
1434 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1435 dev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1436 }
1437
1438 // Connect to trace sources at GW nodes.
1439
1440 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1441 Callback<void, const Time&, const Address&> callback =
1442 MakeCallback(&SatStatsRtnDevDelayHelper::RxDelayCallback, this);
1443
1444 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1445 {
1446 NetDeviceContainer devs = GetGwSatNetDevice(*it);
1447
1448 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1449 {
1450 NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
1451
1452 if ((*itDev)->TraceConnectWithoutContext("RxDelay", callback))
1453 {
1454 NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1455 << " device #" << (*itDev)->GetIfIndex());
1456
1457 // Enable statistics-related tags and trace sources on the device.
1458 (*itDev)->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1459 }
1460 else
1461 {
1462 NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatNetDevice"
1463 << " at node ID " << (*it)->GetId() << " device #"
1464 << (*itDev)->GetIfIndex());
1465 }
1466
1467 } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1468
1469 } // end of `for (NodeContainer::Iterator it = gws)`
1470
1471} // end of `void DoInstallProbes ();`
1472
1473// RETURN LINK MAC-LEVEL //////////////////////////////////////////////////////
1474
1475NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnMacDelayHelper);
1476
1478 : SatStatsDelayHelper(satHelper)
1479{
1480 NS_LOG_FUNCTION(this << satHelper);
1481}
1482
1484{
1485 NS_LOG_FUNCTION(this);
1486}
1487
1488TypeId // static
1490{
1491 static TypeId tid = TypeId("ns3::SatStatsRtnMacDelayHelper").SetParent<SatStatsDelayHelper>();
1492 return tid;
1493}
1494
1495void
1497{
1498 NS_LOG_FUNCTION(this);
1499
1500 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1501 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1502 {
1503 // Create a map of UT addresses and identifiers.
1505
1506 // Enable statistics-related tags and trace sources on the device.
1507 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1508 Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1509 NS_ASSERT(satDev != nullptr);
1510 Ptr<SatMac> satMac = satDev->GetMac();
1511 NS_ASSERT(satMac != nullptr);
1512 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1513 satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1514 }
1515
1516 // Connect to trace sources at GW nodes.
1517
1518 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1519 Callback<void, const Time&, const Address&> callback =
1520 MakeCallback(&SatStatsRtnMacDelayHelper::RxDelayCallback, this);
1521
1522 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1523 {
1524 NetDeviceContainer devs = GetGwSatNetDevice(*it);
1525
1526 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1527 {
1528 Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1529 NS_ASSERT(satDev != nullptr);
1530 Ptr<SatMac> satMac = satDev->GetMac();
1531 NS_ASSERT(satMac != nullptr);
1532
1533 // Connect the object to the probe.
1534 if (satMac->TraceConnectWithoutContext("RxDelay", callback))
1535 {
1536 NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1537 << " device #" << satDev->GetIfIndex());
1538
1539 // Enable statistics-related tags and trace sources on the device.
1540 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1541 satMac->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1542 }
1543 else
1544 {
1545 NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatNetDevice"
1546 << " at node ID " << (*it)->GetId() << " device #"
1547 << satDev->GetIfIndex());
1548 }
1549
1550 } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1551
1552 } // end of `for (NodeContainer::Iterator it = gws)`
1553
1554} // end of `void DoInstallProbes ();`
1555
1556// RETURN LINK PHY-LEVEL //////////////////////////////////////////////////////
1557
1558NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnPhyDelayHelper);
1559
1561 : SatStatsDelayHelper(satHelper)
1562{
1563 NS_LOG_FUNCTION(this << satHelper);
1564}
1565
1567{
1568 NS_LOG_FUNCTION(this);
1569}
1570
1571TypeId // static
1573{
1574 static TypeId tid = TypeId("ns3::SatStatsRtnPhyDelayHelper").SetParent<SatStatsDelayHelper>();
1575 return tid;
1576}
1577
1578void
1580{
1581 NS_LOG_FUNCTION(this);
1582
1583 NodeContainer sats = Singleton<SatTopology>::Get()->GetOrbiterNodes();
1584
1585 for (NodeContainer::Iterator it = sats.Begin(); it != sats.End(); ++it)
1586 {
1587 Ptr<SatPhy> satPhy;
1588 Ptr<NetDevice> dev = GetSatSatOrbiterNetDevice(*it);
1589 Ptr<SatOrbiterNetDevice> satOrbiterDev = dev->GetObject<SatOrbiterNetDevice>();
1590 NS_ASSERT(satOrbiterDev != nullptr);
1591 std::map<uint32_t, Ptr<SatPhy>> satOrbiterFeederPhys = satOrbiterDev->GetFeederPhy();
1592 for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterFeederPhys.begin();
1593 it2 != satOrbiterFeederPhys.end();
1594 ++it2)
1595 {
1596 satPhy = it2->second;
1597 NS_ASSERT(satPhy != nullptr);
1598 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1599 }
1600 std::map<uint32_t, Ptr<SatPhy>> satOrbiterUserPhys = satOrbiterDev->GetUserPhy();
1601 for (std::map<uint32_t, Ptr<SatPhy>>::iterator it2 = satOrbiterUserPhys.begin();
1602 it2 != satOrbiterUserPhys.end();
1603 ++it2)
1604 {
1605 satPhy = it2->second;
1606 NS_ASSERT(satPhy != nullptr);
1607 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1608 }
1609 } // end of `for (it = sats.Begin(); it != sats.End (); ++it)`
1610
1611 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
1612 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
1613 {
1614 // Create a map of UT addresses and identifiers.
1616
1617 // Enable statistics-related tags and trace sources on the device.
1618 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
1619 Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
1620 NS_ASSERT(satDev != nullptr);
1621 Ptr<SatPhy> satPhy = satDev->GetPhy();
1622 NS_ASSERT(satPhy != nullptr);
1623 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1624 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1625 }
1626
1627 // Connect to trace sources at GW nodes.
1628
1629 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
1630 Callback<void, const Time&, const Address&> callback =
1631 MakeCallback(&SatStatsRtnPhyDelayHelper::RxDelayCallback, this);
1632
1633 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
1634 {
1635 NetDeviceContainer devs = GetGwSatNetDevice(*it);
1636
1637 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
1638 {
1639 Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
1640 NS_ASSERT(satDev != nullptr);
1641 Ptr<SatPhy> satPhy = satDev->GetPhy();
1642 NS_ASSERT(satPhy != nullptr);
1643
1644 // Connect the object to the probe.
1645 if (satPhy->TraceConnectWithoutContext("RxDelay", callback))
1646 {
1647 NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
1648 << " device #" << satDev->GetIfIndex());
1649
1650 // Enable statistics-related tags and trace sources on the device.
1651 satDev->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1652 satPhy->SetAttribute("EnableStatisticsTags", BooleanValue(true));
1653 }
1654 else
1655 {
1656 NS_FATAL_ERROR("Error connecting to RxDelay trace source of SatNetDevice"
1657 << " at node ID " << (*it)->GetId() << " device #"
1658 << satDev->GetIfIndex());
1659 }
1660
1661 } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
1662
1663 } // end of `for (NodeContainer::Iterator it = gws)`
1664
1665} // end of `void DoInstallProbes ();`
1666
1667} // end of namespace ns3
SatNetDevice to be utilized in the UT and GW nodes.
SatOrbiterNetDevice to be utilized in geostationary satellite.
Base class for delay statistics helpers.
CollectorMap m_terminalCollectors
Maintains a list of collectors created by this helper.
void InstallProbes()
Set up several probes or other means of listeners and connect them to the collectors.
void SetAveragingMode(bool averagingMode)
void DoInstall()
Install the probes, collectors, and aggregators necessary to produce the statistics output.
void RxDelayCallback(const Time &delay, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
virtual void DoInstallProbes()=0
void PassSampleToCollector(const Time &delay, uint32_t identifier)
Find a collector with the right identifier and pass a sample data to it.
Ptr< DataCollectionObject > m_aggregator
The aggregator created by this helper.
static TypeId GetTypeId()
inherited from ObjectBase base class
bool m_averagingMode
AveragingMode attribute.
Ptr< DistributionCollector > m_averagingCollector
The final collector utilized in averaged output (histogram, PDF, and CDF).
bool DisconnectProbeFromCollector(Ptr< Probe > probe, uint32_t identifier)
Disconnect the probe from the right collector.
SatStatsDelayHelper(Ptr< const SatHelper > satHelper)
virtual ~SatStatsDelayHelper()
/ Destructor.
bool ConnectProbeToCollector(Ptr< Probe > probe, uint32_t identifier)
Connect the probe to the right collector.
Produce forward link application-level delay statistics from a satellite module simulation.
static TypeId GetTypeId()
inherited from ObjectBase base class
virtual void UpdateIdentifierOnProbes()
Change identifier used on probes, when handovers occur.
static void RxCallback(Ptr< SatStatsFwdAppDelayHelper > helper, uint32_t identifier, Ptr< const Packet > packet, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
SatStatsFwdAppDelayHelper(Ptr< const SatHelper > satHelper)
std::map< Ptr< Probe >, std::pair< Ptr< Node >, uint32_t > > m_probes
Maintains a list of probes created by this helper.
virtual ~SatStatsFwdAppDelayHelper()
Destructor for SatStatsFwdAppDelayHelper.
Produce forward link device-level delay statistics from a satellite module simulation.
SatStatsFwdDevDelayHelper(Ptr< const SatHelper > satHelper)
std::map< Ptr< Probe >, std::pair< Ptr< Node >, uint32_t > > m_probes
Maintains a list of probes created by this helper.
virtual void UpdateIdentifierOnProbes()
Change identifier used on probes, when handovers occur.
static TypeId GetTypeId()
inherited from ObjectBase base class
Produce forward link MAC-level delay statistics from a satellite module simulation.
std::map< Ptr< Probe >, std::pair< Ptr< Node >, uint32_t > > m_probes
Maintains a list of probes created by this helper.
SatStatsFwdMacDelayHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
virtual void UpdateIdentifierOnProbes()
Change identifier used on probes, when handovers occur.
Produce forward link PHY-level delay statistics from a satellite module simulation.
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
SatStatsFwdPhyDelayHelper(Ptr< const SatHelper > satHelper)
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
Produce return link application-level delay statistics from a satellite module simulation.
static TypeId GetTypeId()
inherited from ObjectBase base class
void Ipv4Callback(const Time &delay, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
void RxCallback(Ptr< const Packet > packet, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
SatStatsRtnAppDelayHelper(Ptr< const SatHelper > satHelper)
void SaveIpv4AddressAndIdentifier(Ptr< Node > utUserNode)
Save the IPv4 address and the proper identifier from the given UT user node.
Produce return link device-level delay statistics from a satellite module simulation.
SatStatsRtnDevDelayHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
Produce return link MAC-level delay statistics from a satellite module simulation.
SatStatsRtnMacDelayHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
Produce return link PHY-level delay statistics from a satellite module simulation.
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsRtnPhyDelayHelper(Ptr< const SatHelper > satHelper)
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.