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 
24 #include <ns3/boolean.h>
25 #include <ns3/callback.h>
26 #include <ns3/data-collection-object.h>
27 #include <ns3/distribution-collector.h>
28 #include <ns3/enum.h>
29 #include <ns3/log.h>
30 #include <ns3/mac48-address.h>
31 #include <ns3/magister-gnuplot-aggregator.h>
32 #include <ns3/multi-file-aggregator.h>
33 #include <ns3/node-container.h>
34 #include <ns3/object-vector.h>
35 #include <ns3/probe.h>
36 #include <ns3/satellite-helper.h>
37 #include <ns3/satellite-id-mapper.h>
38 #include <ns3/satellite-net-device.h>
39 #include <ns3/satellite-phy-rx-carrier.h>
40 #include <ns3/satellite-phy-rx.h>
41 #include <ns3/satellite-phy.h>
42 #include <ns3/satellite-sinr-probe.h>
43 #include <ns3/scalar-collector.h>
44 #include <ns3/singleton.h>
45 #include <ns3/string.h>
46 #include <ns3/unit-conversion-collector.h>
47 
48 #include <sstream>
49 
50 NS_LOG_COMPONENT_DEFINE("SatStatsCompositeSinrHelper");
51 
52 namespace ns3
53 {
54 
55 NS_OBJECT_ENSURE_REGISTERED(SatStatsCompositeSinrHelper);
56 
58  : SatStatsHelper(satHelper)
59 {
60  NS_LOG_FUNCTION(this << satHelper);
61 }
62 
64 {
65  NS_LOG_FUNCTION(this);
66 }
67 
68 TypeId // static
70 {
71  static TypeId tid = TypeId("ns3::SatStatsCompositeSinrHelper").SetParent<SatStatsHelper>();
72  return tid;
73 }
74 
75 void
77 {
78  NS_LOG_FUNCTION(this);
79 
80  switch (GetOutputType())
81  {
83  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
84  << " is not a valid output type for this statistics.");
85  break;
86 
88  // Setup aggregator.
89  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
90  "OutputFileName",
91  StringValue(GetOutputFileName()),
92  "MultiFileMode",
93  BooleanValue(false),
94  "EnableContextPrinting",
95  BooleanValue(true),
96  "GeneralHeading",
97  StringValue(GetIdentifierHeading("sinr_db")));
98 
99  // Setup collectors.
100  m_terminalCollectors.SetType("ns3::ScalarCollector");
101  m_terminalCollectors.SetAttribute("InputDataType",
102  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
103  m_terminalCollectors.SetAttribute(
104  "OutputType",
105  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
107  m_terminalCollectors.ConnectToAggregator("Output",
108  m_aggregator,
109  &MultiFileAggregator::Write1d);
110  break;
111  }
112 
114  // Setup aggregator.
115  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
116  "OutputFileName",
117  StringValue(GetOutputFileName()),
118  "GeneralHeading",
119  StringValue(GetTimeHeading("sinr_db")));
120 
121  // Setup collectors.
122  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
123  m_terminalCollectors.SetAttribute("ConversionType",
124  EnumValue(UnitConversionCollector::TRANSPARENT));
126  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
127  m_aggregator,
128  &MultiFileAggregator::Write2d);
129  break;
130  }
131 
135  // Setup aggregator.
136  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
137  "OutputFileName",
138  StringValue(GetOutputFileName()),
139  "GeneralHeading",
140  StringValue(GetDistributionHeading("sinr_db")));
141 
142  // Setup collectors.
143  m_terminalCollectors.SetType("ns3::DistributionCollector");
144  DistributionCollector::OutputType_t outputType =
145  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
147  {
148  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
149  }
151  {
152  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
153  }
154  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
156  m_terminalCollectors.ConnectToAggregator("Output",
157  m_aggregator,
158  &MultiFileAggregator::Write2d);
159  m_terminalCollectors.ConnectToAggregator("OutputString",
160  m_aggregator,
161  &MultiFileAggregator::AddContextHeading);
162  m_terminalCollectors.ConnectToAggregator("Warning",
163  m_aggregator,
164  &MultiFileAggregator::EnableContextWarning);
165  break;
166  }
167 
170  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
171  << " is not a valid output type for this statistics.");
172  break;
173 
175  // Setup aggregator.
176  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
177  "OutputPath",
178  StringValue(GetOutputPath()),
179  "OutputFileName",
180  StringValue(GetName()));
181  Ptr<MagisterGnuplotAggregator> plotAggregator =
182  m_aggregator->GetObject<MagisterGnuplotAggregator>();
183  NS_ASSERT(plotAggregator != nullptr);
184  // plot->SetTitle ("");
185  plotAggregator->SetLegend("Time (in seconds)", "SINR (in dB)");
186  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
187 
188  // Setup collectors.
189  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
190  m_terminalCollectors.SetAttribute("ConversionType",
191  EnumValue(UnitConversionCollector::TRANSPARENT));
193  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
194  it != m_terminalCollectors.End();
195  ++it)
196  {
197  const std::string context = it->second->GetName();
198  plotAggregator->Add2dDataset(context, context);
199  }
200  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
201  m_aggregator,
202  &MagisterGnuplotAggregator::Write2d);
203  break;
204  }
205 
209  // Setup aggregator.
210  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
211  "OutputPath",
212  StringValue(GetOutputPath()),
213  "OutputFileName",
214  StringValue(GetName()));
215  Ptr<MagisterGnuplotAggregator> plotAggregator =
216  m_aggregator->GetObject<MagisterGnuplotAggregator>();
217  NS_ASSERT(plotAggregator != nullptr);
218  // plot->SetTitle ("");
219  plotAggregator->SetLegend("SINR (in dB)", "Frequency");
220  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
221 
222  // Setup collectors.
223  m_terminalCollectors.SetType("ns3::DistributionCollector");
224  DistributionCollector::OutputType_t outputType =
225  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
227  {
228  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
229  }
231  {
232  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
233  }
234  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
236  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
237  it != m_terminalCollectors.End();
238  ++it)
239  {
240  const std::string context = it->second->GetName();
241  plotAggregator->Add2dDataset(context, context);
242  }
243  m_terminalCollectors.ConnectToAggregator("Output",
244  m_aggregator,
245  &MagisterGnuplotAggregator::Write2d);
246  break;
247  }
248 
249  default:
250  NS_FATAL_ERROR("SatStatsCompositeSinrHelper - Invalid output type");
251  break;
252  }
253 
254  // Setup probes and connect them to the collectors.
255  InstallProbes();
256 
257 } // end of `void DoInstall ();`
258 
259 void
261 {
262  // The method below is supposed to be implemented by the child class.
263  DoInstallProbes();
264 }
265 
266 // FORWARD LINK ///////////////////////////////////////////////////////////////
267 
268 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdCompositeSinrHelper);
269 
271  : SatStatsCompositeSinrHelper(satHelper)
272 {
273  NS_LOG_FUNCTION(this << satHelper);
274 }
275 
277 {
278  NS_LOG_FUNCTION(this);
279 }
280 
281 TypeId // static
283 {
284  static TypeId tid =
285  TypeId("ns3::SatStatsFwdCompositeSinrHelper").SetParent<SatStatsCompositeSinrHelper>();
286  return tid;
287 }
288 
289 void
291 {
292  NS_LOG_FUNCTION(this);
293  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
294 
295  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
296  {
297  const int32_t utId = GetUtId(*it);
298  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
299  const uint32_t identifier = GetIdentifierForUt(*it);
300 
301  // Create the probe.
302  std::ostringstream probeName;
303  probeName << utId;
304  Ptr<SatSinrProbe> probe = CreateObject<SatSinrProbe>();
305  probe->SetName(probeName.str());
306 
307  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
308  Ptr<SatNetDevice> satDev = dev->GetObject<SatNetDevice>();
309  NS_ASSERT(satDev != nullptr);
310  Ptr<SatPhy> satPhy = satDev->GetPhy();
311  NS_ASSERT(satPhy != nullptr);
312  Ptr<SatPhyRx> satPhyRx = satPhy->GetPhyRx();
313  NS_ASSERT(satPhyRx != nullptr);
314  ObjectVectorValue carriers;
315  satPhyRx->GetAttribute("RxCarrierList", carriers);
316  NS_LOG_DEBUG(this << " Node ID " << (*it)->GetId() << " device #" << dev->GetIfIndex()
317  << " has " << carriers.GetN() << " RX carriers");
318 
319  for (ObjectVectorValue::Iterator itCarrier = carriers.Begin(); itCarrier != carriers.End();
320  ++itCarrier)
321  {
322  // Connect the object to the probe.
323  if (probe->ConnectByObject("Sinr", itCarrier->second))
324  {
325  // Connect the probe to the right collector.
326  bool ret = false;
327  switch (GetOutputType())
328  {
331  ret = m_terminalCollectors.ConnectWithProbe(probe->GetObject<Probe>(),
332  "OutputSinr",
333  identifier,
334  &ScalarCollector::TraceSinkDouble);
335  break;
336 
339  ret = m_terminalCollectors.ConnectWithProbe(
340  probe->GetObject<Probe>(),
341  "OutputSinr",
342  identifier,
343  &UnitConversionCollector::TraceSinkDouble);
344  break;
345 
352  ret = m_terminalCollectors.ConnectWithProbe(
353  probe->GetObject<Probe>(),
354  "OutputSinr",
355  identifier,
356  &DistributionCollector::TraceSinkDouble);
357  break;
358 
359  default:
360  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
361  << " is not a valid output type for this statistics.");
362  break;
363 
364  } // end of `switch (GetOutputType ())`
365 
366  if (ret)
367  {
368  NS_LOG_INFO(this << " created probe " << probeName.str()
369  << ", connected to collector " << identifier);
370  m_probes.push_back(probe->GetObject<Probe>());
371  }
372  else
373  {
374  NS_LOG_WARN(this << " unable to connect probe " << probeName.str()
375  << " to collector " << identifier);
376  }
377 
378  } // end of `if (probe->ConnectByObject ("Sinr", itCarrier->second))`
379  else
380  {
381  NS_FATAL_ERROR("Error connecting to Sinr trace source"
382  << " of SatPhyRxCarrier"
383  << " at node ID " << (*it)->GetId() << " device #"
384  << dev->GetIfIndex() << " RX carrier #" << itCarrier->first);
385  }
386 
387  } // end of `for (ObjectVectorValue::Iterator itCarrier = carriers)`
388 
389  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
390 
391 } // end of `void DoInstallProbes ();`
392 
393 // RETURN LINK ////////////////////////////////////////////////////////////////
394 
395 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnCompositeSinrHelper);
396 
398  : SatStatsCompositeSinrHelper(satHelper)
399 {
400  NS_LOG_FUNCTION(this << satHelper);
401 }
402 
404 {
405  NS_LOG_FUNCTION(this);
406 }
407 
408 TypeId // static
410 {
411  static TypeId tid =
412  TypeId("ns3::SatStatsRtnCompositeSinrHelper").SetParent<SatStatsCompositeSinrHelper>();
413  return tid;
414 }
415 
416 void
418 {
419  NS_LOG_FUNCTION(this);
420 
421  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
422  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
423  {
424  // Create a map of UT addresses and identifiers.
426  }
427 
428  // Connect to trace sources at GW nodes.
429 
430  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
431  Callback<void, double, const Address&> callback =
433 
434  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
435  {
436  NetDeviceContainer devs = GetGwSatNetDevice(*it);
437 
438  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
439  {
440  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
441  NS_ASSERT(satDev != nullptr);
442  Ptr<SatPhy> satPhy = satDev->GetPhy();
443  NS_ASSERT(satPhy != nullptr);
444  Ptr<SatPhyRx> satPhyRx = satPhy->GetPhyRx();
445  NS_ASSERT(satPhyRx != nullptr);
446  ObjectVectorValue carriers;
447  satPhyRx->GetAttribute("RxCarrierList", carriers);
448  NS_LOG_DEBUG(this << " Node ID " << (*it)->GetId() << " device #"
449  << (*itDev)->GetIfIndex() << " has " << carriers.GetN()
450  << " RX carriers");
451 
452  for (ObjectVectorValue::Iterator itCarrier = carriers.Begin();
453  itCarrier != carriers.End();
454  ++itCarrier)
455  {
456  if (itCarrier->second->TraceConnectWithoutContext("Sinr", callback))
457  {
458  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
459  << " device #" << (*itDev)->GetIfIndex() << " RX carrier #"
460  << itCarrier->first);
461  }
462  else
463  {
464  NS_FATAL_ERROR("Error connecting to Sinr trace source"
465  << " of SatPhyRxCarrier"
466  << " at node ID " << (*it)->GetId() << " device #"
467  << (*itDev)->GetIfIndex() << " RX carrier #"
468  << itCarrier->first);
469  }
470 
471  } // end of `for (ObjectVectorValue::Iterator itCarrier = carriers)`
472 
473  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
474 
475  } // end of `for (NodeContainer::Iterator it = gws)`
476 
477 } // end of `void DoInstallProbes ();`
478 
479 void
480 SatStatsRtnCompositeSinrHelper::SinrCallback(double sinrDb, const Address& from)
481 {
482  // NS_LOG_FUNCTION (this << sinrDb << from);
483 
484  if (from.IsInvalid())
485  {
486  NS_LOG_WARN(this << " discarding a SINR trace of " << sinrDb << " dB"
487  << " from statistics collection because of"
488  << " invalid sender address");
489  }
490  else
491  {
492  // Determine the identifier associated with the sender address.
493  std::map<const Address, uint32_t>::const_iterator it = m_identifierMap.find(from);
494 
495  if (it == m_identifierMap.end())
496  {
497  NS_LOG_WARN(this << " discarding a SINR trace of " << sinrDb << " dB"
498  << " from statistics collection because of"
499  << " unknown sender address " << from);
500  }
501  else
502  {
503  // Find the collector with the right identifier.
504  Ptr<DataCollectionObject> collector = m_terminalCollectors.Get(it->second);
505  NS_ASSERT_MSG(collector != nullptr,
506  "Unable to find collector with identifier " << it->second);
507 
508  switch (GetOutputType())
509  {
512  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
513  NS_ASSERT(c != nullptr);
514  c->TraceSinkDouble(0.0, sinrDb);
515  break;
516  }
517 
520  Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
521  NS_ASSERT(c != nullptr);
522  c->TraceSinkDouble(0.0, sinrDb);
523  break;
524  }
525 
532  Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
533  NS_ASSERT(c != nullptr);
534  c->TraceSinkDouble(0.0, sinrDb);
535  break;
536  }
537 
538  default:
539  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
540  << " is not a valid output type for this statistics.");
541  break;
542 
543  } // end of `switch (GetOutputType ())`
544 
545  } // end of `if (it == m_identifierMap.end ())`
546 
547  } // end of else of `if (from.IsInvalid ())`
548 
549 } // end of `void SinrCallback (double, const Address &);`
550 
551 void
553 {
554  NS_LOG_FUNCTION(this << utNode->GetId());
555 
556  const SatIdMapper* satIdMapper = Singleton<SatIdMapper>::Get();
557  const Address addr = satIdMapper->GetUtMacWithNode(utNode);
558 
559  if (addr.IsInvalid())
560  {
561  NS_LOG_WARN(this << " Node " << utNode->GetId() << " is not a valid UT");
562  }
563  else
564  {
565  const uint32_t identifier = GetIdentifierForUt(utNode);
566  m_identifierMap[addr] = identifier;
567  NS_LOG_INFO(this << " associated address " << addr << " with identifier " << identifier);
568  }
569 }
570 
571 } // end of namespace ns3
Class for ID-mapper.
Address GetUtMacWithNode(Ptr< Node > utNode) const
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
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.
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.
std::list< Ptr< Probe > > m_probes
Maintains a list of probes created by this helper.
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsFwdCompositeSinrHelper(Ptr< const SatHelper > satHelper)
Parent abstract class of all satellite statistics helpers.
Ptr< const SatHelper > GetSatHelper() const
static NetDeviceContainer GetGwSatNetDevice(Ptr< Node > gwNode)
static std::string GetOutputTypeName(OutputType_t outputType)
virtual std::string GetIdentifierHeading(std::string dataLabel) const
virtual std::string GetOutputPath() const
Ptr< DataCollectionObject > CreateAggregator(std::string aggregatorTypeId, std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue(), std::string n5="", const AttributeValue &v5=EmptyAttributeValue())
Create the aggregator according to the output type.
virtual std::string GetOutputFileName() const
Compute the path and file name where statistics output should be written to.
uint32_t GetUtId(Ptr< Node > utNode) const
uint32_t CreateCollectorPerIdentifier(CollectorMap &collectorMap) const
Create one collector instance for each identifier in the simulation.
static Ptr< NetDevice > GetUtSatNetDevice(Ptr< Node > utNode)
OutputType_t GetOutputType() const
uint32_t GetIdentifierForUt(Ptr< Node > utNode) const
std::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.
void SaveAddressAndIdentifier(Ptr< Node > utNode)
Save the address and the proper identifier from the given UT node.
SatStatsRtnCompositeSinrHelper(Ptr< const SatHelper > satHelper)
std::map< const Address, uint32_t > m_identifierMap
Map of address and the identifier associated with it (for return link).
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.