Loading...
Searching...
No Matches
satellite-stats-composite-sinr-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
25
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/log.h"
32#include "ns3/mac48-address.h"
33#include "ns3/magister-gnuplot-aggregator.h"
34#include "ns3/multi-file-aggregator.h"
35#include "ns3/node-container.h"
36#include "ns3/object-vector.h"
37#include "ns3/probe.h"
38#include "ns3/satellite-helper.h"
39#include "ns3/satellite-id-mapper.h"
40#include "ns3/satellite-net-device.h"
41#include "ns3/satellite-phy-rx-carrier.h"
42#include "ns3/satellite-phy-rx.h"
43#include "ns3/satellite-phy.h"
44#include "ns3/satellite-topology.h"
45#include "ns3/scalar-collector.h"
46#include "ns3/singleton.h"
47#include "ns3/string.h"
48#include "ns3/unit-conversion-collector.h"
49
50#include <map>
51#include <sstream>
52#include <string>
53#include <utility>
54
55NS_LOG_COMPONENT_DEFINE("SatStatsCompositeSinrHelper");
56
57namespace ns3
58{
59
60NS_OBJECT_ENSURE_REGISTERED(SatStatsCompositeSinrHelper);
61
63 : SatStatsHelper(satHelper)
64{
65 NS_LOG_FUNCTION(this << satHelper);
66}
67
72
73TypeId // static
75{
76 static TypeId tid = TypeId("ns3::SatStatsCompositeSinrHelper").SetParent<SatStatsHelper>();
77 return tid;
78}
79
80void
82{
83 NS_LOG_FUNCTION(this);
84
85 switch (GetOutputType())
86 {
88 NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
89 << " is not a valid output type for this statistics.");
90 break;
91
93 // Setup aggregator.
94 m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
95 "OutputFileName",
96 StringValue(GetOutputFileName()),
97 "MultiFileMode",
98 BooleanValue(false),
99 "EnableContextPrinting",
100 BooleanValue(true),
101 "GeneralHeading",
102 StringValue(GetIdentifierHeading("sinr_db")));
103
104 // Setup collectors.
105 m_terminalCollectors.SetType("ns3::ScalarCollector");
106 m_terminalCollectors.SetAttribute("InputDataType",
107 EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
108 m_terminalCollectors.SetAttribute(
109 "OutputType",
110 EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
112 m_terminalCollectors.ConnectToAggregator("Output",
114 &MultiFileAggregator::Write1d);
115 break;
116 }
117
119 // Setup aggregator.
120 m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
121 "OutputFileName",
122 StringValue(GetOutputFileName()),
123 "GeneralHeading",
124 StringValue(GetTimeHeading("sinr_db")));
125
126 // Setup collectors.
127 m_terminalCollectors.SetType("ns3::UnitConversionCollector");
128 m_terminalCollectors.SetAttribute("ConversionType",
129 EnumValue(UnitConversionCollector::TRANSPARENT));
131 m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
133 &MultiFileAggregator::Write2d);
134 break;
135 }
136
140 // Setup aggregator.
141 m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
142 "OutputFileName",
143 StringValue(GetOutputFileName()),
144 "GeneralHeading",
145 StringValue(GetDistributionHeading("sinr_db")));
146
147 // Setup collectors.
148 m_terminalCollectors.SetType("ns3::DistributionCollector");
149 DistributionCollector::OutputType_t outputType =
150 DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
152 {
153 outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
154 }
156 {
157 outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
158 }
159 m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
161 m_terminalCollectors.ConnectToAggregator("Output",
163 &MultiFileAggregator::Write2d);
164 m_terminalCollectors.ConnectToAggregator("OutputString",
166 &MultiFileAggregator::AddContextHeading);
167 m_terminalCollectors.ConnectToAggregator("Warning",
169 &MultiFileAggregator::EnableContextWarning);
170 break;
171 }
172
175 NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
176 << " is not a valid output type for this statistics.");
177 break;
178
180 // Setup aggregator.
181 m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
182 "OutputPath",
183 StringValue(GetOutputPath()),
184 "OutputFileName",
185 StringValue(GetName()));
186 Ptr<MagisterGnuplotAggregator> plotAggregator =
187 m_aggregator->GetObject<MagisterGnuplotAggregator>();
188 NS_ASSERT(plotAggregator != nullptr);
189 // plot->SetTitle ("");
190 plotAggregator->SetLegend("Time (in seconds)", "SINR (in dB)");
191 plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
192
193 // Setup collectors.
194 m_terminalCollectors.SetType("ns3::UnitConversionCollector");
195 m_terminalCollectors.SetAttribute("ConversionType",
196 EnumValue(UnitConversionCollector::TRANSPARENT));
198 for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
199 it != m_terminalCollectors.End();
200 ++it)
201 {
202 const std::string context = it->second->GetName();
203 plotAggregator->Add2dDataset(context, context);
204 }
205 m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
207 &MagisterGnuplotAggregator::Write2d);
208 break;
209 }
210
214 // Setup aggregator.
215 m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
216 "OutputPath",
217 StringValue(GetOutputPath()),
218 "OutputFileName",
219 StringValue(GetName()));
220 Ptr<MagisterGnuplotAggregator> plotAggregator =
221 m_aggregator->GetObject<MagisterGnuplotAggregator>();
222 NS_ASSERT(plotAggregator != nullptr);
223 // plot->SetTitle ("");
224 plotAggregator->SetLegend("SINR (in dB)", "Frequency");
225 plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
226
227 // Setup collectors.
228 m_terminalCollectors.SetType("ns3::DistributionCollector");
229 DistributionCollector::OutputType_t outputType =
230 DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
232 {
233 outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
234 }
236 {
237 outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
238 }
239 m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
241 for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
242 it != m_terminalCollectors.End();
243 ++it)
244 {
245 const std::string context = it->second->GetName();
246 plotAggregator->Add2dDataset(context, context);
247 }
248 m_terminalCollectors.ConnectToAggregator("Output",
250 &MagisterGnuplotAggregator::Write2d);
251 break;
252 }
253
254 default:
255 NS_FATAL_ERROR("SatStatsCompositeSinrHelper - Invalid output type");
256 break;
257 }
258
259 // Setup probes and connect them to the collectors.
261
262} // end of `void DoInstall ();`
263
264void
266{
267 // The method below is supposed to be implemented by the child class.
269}
270
271bool
272SatStatsCompositeSinrHelper::ConnectProbeToCollector(Ptr<Probe> probe, uint32_t identifier)
273{
274 NS_LOG_FUNCTION(this << probe << probe->GetName() << identifier);
275
276 // Connect the probe to the right collector.
277 bool ret = false;
278 switch (GetOutputType())
279 {
282 ret = m_terminalCollectors.ConnectWithProbe(probe->GetObject<Probe>(),
283 "OutputSinr",
284 identifier,
285 &ScalarCollector::TraceSinkDouble);
286 break;
287
290 ret = m_terminalCollectors.ConnectWithProbe(probe->GetObject<Probe>(),
291 "OutputSinr",
292 identifier,
293 &UnitConversionCollector::TraceSinkDouble);
294 break;
295
302 ret = m_terminalCollectors.ConnectWithProbe(probe->GetObject<Probe>(),
303 "OutputSinr",
304 identifier,
305 &DistributionCollector::TraceSinkDouble);
306 break;
307
308 default:
309 NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
310 << " is not a valid output type for this statistics.");
311 break;
312
313 } // end of `switch (GetOutputType ())`
314
315 if (ret)
316 {
317 NS_LOG_INFO(this << " created probe " << probe->GetName() << ", connected to collector "
318 << identifier);
319 }
320 else
321 {
322 NS_LOG_WARN(this << " unable to connect probe " << probe->GetName() << " to collector "
323 << identifier);
324 }
325
326 return ret;
327}
328
329bool
331{
332 NS_LOG_FUNCTION(this << probe << probe->GetName() << identifier);
333
334 // Connect the probe to the right collector.
335 bool ret = false;
336 switch (GetOutputType())
337 {
340 ret = m_terminalCollectors.DisconnectWithProbe(probe->GetObject<Probe>(),
341 "OutputSinr",
342 identifier,
343 &ScalarCollector::TraceSinkDouble);
344 break;
345
348 ret = m_terminalCollectors.DisconnectWithProbe(probe->GetObject<Probe>(),
349 "OutputSinr",
350 identifier,
351 &UnitConversionCollector::TraceSinkDouble);
352 break;
353
360 ret = m_terminalCollectors.DisconnectWithProbe(probe->GetObject<Probe>(),
361 "OutputSinr",
362 identifier,
363 &DistributionCollector::TraceSinkDouble);
364 break;
365
366 default:
367 NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
368 << " is not a valid output type for this statistics.");
369 break;
370
371 } // end of `switch (GetOutputType ())`
372
373 if (ret)
374 {
375 NS_LOG_INFO(this << " probe " << probe->GetName() << ", disconnected from collector "
376 << identifier);
377 }
378 else
379 {
380 NS_LOG_WARN(this << " unable to disconnect probe " << probe->GetName() << " from collector "
381 << identifier);
382 }
383
384 return ret;
385}
386
387// FORWARD LINK ///////////////////////////////////////////////////////////////
388
389NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdCompositeSinrHelper);
390
392 : SatStatsCompositeSinrHelper(satHelper)
393{
394 NS_LOG_FUNCTION(this << satHelper);
395}
396
401
402TypeId // static
404{
405 static TypeId tid =
406 TypeId("ns3::SatStatsFwdCompositeSinrHelper").SetParent<SatStatsCompositeSinrHelper>();
407 return tid;
408}
409
410void
412{
413 NS_LOG_FUNCTION(this);
414 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
415
416 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
417 {
418 const int32_t utId = GetUtId(*it);
419 NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
420 const uint32_t identifier = GetIdentifierForUt(*it);
421
422 // Create the probe.
423 std::ostringstream probeName;
424 probeName << utId;
425 Ptr<SatSinrProbe> probe = CreateObject<SatSinrProbe>();
426 probe->SetName(probeName.str());
427
428 Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
429 Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
430 NS_ASSERT(satDev != nullptr);
431 Ptr<SatPhy> satPhy = satDev->GetPhy();
432 NS_ASSERT(satPhy != nullptr);
433 Ptr<SatPhyRx> satPhyRx = satPhy->GetPhyRx();
434 NS_ASSERT(satPhyRx != nullptr);
435 ObjectVectorValue carriers;
436 satPhyRx->GetAttribute("RxCarrierList", carriers);
437 NS_LOG_DEBUG(this << " Node ID " << (*it)->GetId() << " device #" << dev->GetIfIndex()
438 << " has " << carriers.GetN() << " RX carriers");
439
440 for (ObjectVectorValue::Iterator itCarrier = carriers.Begin(); itCarrier != carriers.End();
441 ++itCarrier)
442 {
443 // Connect the object to the probe.
444 if (probe->ConnectByObject("Sinr", itCarrier->second) &&
445 ConnectProbeToCollector(probe, identifier))
446 {
447 m_probes.insert(
448 std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
449 } // end of `if (probe->ConnectByObject ("Sinr", itCarrier->second))`
450 else
451 {
452 NS_FATAL_ERROR("Error connecting to Sinr trace source"
453 << " of SatPhyRxCarrier" << " at node ID " << (*it)->GetId()
454 << " device #" << dev->GetIfIndex() << " RX carrier #"
455 << itCarrier->first);
456 }
457
458 } // end of `for (ObjectVectorValue::Iterator itCarrier = carriers)`
459
460 } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
461
462} // end of `void DoInstallProbes ();`
463
464void
466{
467 NS_LOG_FUNCTION(this);
468
469 std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
470
471 for (it = m_probes.begin(); it != m_probes.end(); it++)
472 {
473 Ptr<Probe> probe = it->first;
474 Ptr<Node> node = it->second.first;
475 uint32_t identifier = it->second.second;
476
477 if (!DisconnectProbeFromCollector(probe, identifier))
478 {
479 NS_FATAL_ERROR("Error disconnecting trace file on handover");
480 }
481
482 identifier = GetIdentifierForUtUser(node);
483
484 if (!ConnectProbeToCollector(probe, identifier))
485 {
486 NS_FATAL_ERROR("Error connecting trace file on handover");
487 }
488
489 it->second.second = identifier;
490 }
491} // end of `void UpdateIdentifierOnProbes ();`
492
493// RETURN LINK ////////////////////////////////////////////////////////////////
494
495NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnCompositeSinrHelper);
496
498 : SatStatsCompositeSinrHelper(satHelper)
499{
500 NS_LOG_FUNCTION(this << satHelper);
501}
502
507
508TypeId // static
510{
511 static TypeId tid =
512 TypeId("ns3::SatStatsRtnCompositeSinrHelper").SetParent<SatStatsCompositeSinrHelper>();
513 return tid;
514}
515
516void
518{
519 NS_LOG_FUNCTION(this);
520
521 NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
522 for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
523 {
524 // Create a map of UT addresses and identifiers.
526 }
527
528 // Connect to trace sources at GW nodes.
529
530 NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
531 Callback<void, double, const Address&> callback =
533
534 for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
535 {
536 NetDeviceContainer devs = GetGwSatNetDevice(*it);
537
538 for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
539 {
540 Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
541 NS_ASSERT(satDev != nullptr);
542 Ptr<SatPhy> satPhy = satDev->GetPhy();
543 NS_ASSERT(satPhy != nullptr);
544 Ptr<SatPhyRx> satPhyRx = satPhy->GetPhyRx();
545 NS_ASSERT(satPhyRx != nullptr);
546 ObjectVectorValue carriers;
547 satPhyRx->GetAttribute("RxCarrierList", carriers);
548 NS_LOG_DEBUG(this << " Node ID " << (*it)->GetId() << " device #"
549 << (*itDev)->GetIfIndex() << " has " << carriers.GetN()
550 << " RX carriers");
551
552 for (ObjectVectorValue::Iterator itCarrier = carriers.Begin();
553 itCarrier != carriers.End();
554 ++itCarrier)
555 {
556 if (itCarrier->second->TraceConnectWithoutContext("Sinr", callback))
557 {
558 NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
559 << " device #" << (*itDev)->GetIfIndex() << " RX carrier #"
560 << itCarrier->first);
561 }
562 else
563 {
564 NS_FATAL_ERROR("Error connecting to Sinr trace source"
565 << " of SatPhyRxCarrier" << " at node ID " << (*it)->GetId()
566 << " device #" << (*itDev)->GetIfIndex() << " RX carrier #"
567 << itCarrier->first);
568 }
569
570 } // end of `for (ObjectVectorValue::Iterator itCarrier = carriers)`
571
572 } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
573
574 } // end of `for (NodeContainer::Iterator it = gws)`
575
576} // end of `void DoInstallProbes ();`
577
578void
579SatStatsRtnCompositeSinrHelper::SinrCallback(double sinrDb, const Address& from)
580{
581 // NS_LOG_FUNCTION (this << sinrDb << from);
582
583 if (from.IsInvalid())
584 {
585 NS_LOG_WARN(this << " discarding a SINR trace of " << sinrDb << " dB"
586 << " from statistics collection because of" << " invalid sender address");
587 }
588 else
589 {
590 // Determine the identifier associated with the sender address.
591 std::map<const Address, uint32_t>::const_iterator it = m_identifierMap.find(from);
592
593 if (it == m_identifierMap.end())
594 {
595 NS_LOG_WARN(this << " discarding a SINR trace of " << sinrDb << " dB"
596 << " from statistics collection because of"
597 << " unknown sender address " << from);
598 }
599 else
600 {
601 // Find the collector with the right identifier.
602 Ptr<DataCollectionObject> collector = m_terminalCollectors.Get(it->second);
603 NS_ASSERT_MSG(collector != nullptr,
604 "Unable to find collector with identifier " << it->second);
605
606 switch (GetOutputType())
607 {
610 Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
611 NS_ASSERT(c != nullptr);
612 c->TraceSinkDouble(0.0, sinrDb);
613 break;
614 }
615
618 Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
619 NS_ASSERT(c != nullptr);
620 c->TraceSinkDouble(0.0, sinrDb);
621 break;
622 }
623
630 Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
631 NS_ASSERT(c != nullptr);
632 c->TraceSinkDouble(0.0, sinrDb);
633 break;
634 }
635
636 default:
637 NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
638 << " is not a valid output type for this statistics.");
639 break;
640
641 } // end of `switch (GetOutputType ())`
642
643 } // end of `if (it == m_identifierMap.end ())`
644
645 } // end of else of `if (from.IsInvalid ())`
646
647} // end of `void SinrCallback (double, const Address &);`
648
649} // end of namespace ns3
SatNetDevice to be utilized in the UT and GW nodes.
Abstract class inherited by SatStatsFwdCompositeSinrHelper and SatStatsRtnCompositeSinrHelper.
static TypeId GetTypeId()
inherited from ObjectBase base class
bool ConnectProbeToCollector(Ptr< Probe > probe, uint32_t identifier)
Connect the probe to the right collector.
void InstallProbes()
Set up several probes or other means of listeners and connect them to the collectors.
void DoInstall()
Install the probes, collectors, and aggregators necessary to produce the statistics output.
CollectorMap m_terminalCollectors
Maintains a list of collectors created by this helper.
bool DisconnectProbeFromCollector(Ptr< Probe > probe, uint32_t identifier)
Disconnect the probe from the right collector.
Ptr< DataCollectionObject > m_aggregator
The aggregator created by this helper.
SatStatsCompositeSinrHelper(Ptr< const SatHelper > satHelper)
Produce forward link composite SINR statistics from a satellite module simulation.
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsFwdCompositeSinrHelper(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.
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.
std::string GetName() const
virtual std::string GetTimeHeading(std::string dataLabel) const
virtual std::string GetDistributionHeading(std::string dataLabel) const
Produce return link composite SINR statistics from a satellite module simulation.
SatStatsRtnCompositeSinrHelper(Ptr< const SatHelper > satHelper)
void SinrCallback(double sinrDb, 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
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.