satellite-stats-carrier-id-helper.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2018 CNES
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: Mathias Ettinger <mettinger@toulouse.viveris.com>
19  */
20 
22 
23 #include <ns3/boolean.h>
24 #include <ns3/callback.h>
25 #include <ns3/data-collection-object.h>
26 #include <ns3/enum.h>
27 #include <ns3/interval-rate-collector.h>
28 #include <ns3/log.h>
29 #include <ns3/mac48-address.h>
30 #include <ns3/magister-gnuplot-aggregator.h>
31 #include <ns3/multi-file-aggregator.h>
32 #include <ns3/node-container.h>
33 #include <ns3/object-vector.h>
34 #include <ns3/satellite-helper.h>
35 #include <ns3/satellite-id-mapper.h>
36 #include <ns3/satellite-net-device.h>
37 #include <ns3/satellite-phy-rx-carrier-marsala.h>
38 #include <ns3/satellite-phy-rx-carrier.h>
39 #include <ns3/satellite-phy-rx.h>
40 #include <ns3/satellite-phy.h>
41 #include <ns3/scalar-collector.h>
42 #include <ns3/singleton.h>
43 #include <ns3/string.h>
44 
45 #include <sstream>
46 
47 NS_LOG_COMPONENT_DEFINE("SatStatsCarrierIdHelper");
48 
49 namespace ns3
50 {
51 
52 // BASE CLASS /////////////////////////////////////////////////////////////////
53 
54 NS_OBJECT_ENSURE_REGISTERED(SatStatsCarrierIdHelper);
55 
56 SatStatsCarrierIdHelper::SatStatsCarrierIdHelper(Ptr<const SatHelper> satHelper)
57  : SatStatsHelper(satHelper)
58 {
59  NS_LOG_FUNCTION(this << satHelper);
60  SetTraceSourceName("DaRxCarrierId");
62 }
63 
65 {
66  NS_LOG_FUNCTION(this);
67 }
68 
69 TypeId // static
71 {
72  static TypeId tid = TypeId("ns3::SatStatsCarrierIdHelper").SetParent<SatStatsHelper>();
73  return tid;
74 }
75 
76 void
77 SatStatsCarrierIdHelper::SetTraceSourceName(std::string traceSourceName)
78 {
79  NS_LOG_FUNCTION(this << traceSourceName);
80  m_traceSourceName = traceSourceName;
81 }
82 
83 std::string
85 {
86  return m_traceSourceName;
87 }
88 
89 void
91 {
92  NS_LOG_FUNCTION(this);
93 
94  switch (GetOutputType())
95  {
97  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
98  << " is not a valid output type for this statistics.");
99  break;
100 
102  // Setup aggregator.
103  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
104  "OutputFileName",
105  StringValue(GetOutputFileName()),
106  "MultiFileMode",
107  BooleanValue(false),
108  "EnableContextPrinting",
109  BooleanValue(true),
110  "GeneralHeading",
111  StringValue(GetIdentifierHeading("carrier_id")));
112 
113  // Setup collectors.
114  m_terminalCollectors.SetType("ns3::ScalarCollector");
115  m_terminalCollectors.SetAttribute("InputDataType",
116  EnumValue(ScalarCollector::INPUT_DATA_TYPE_UINTEGER));
117  m_terminalCollectors.SetAttribute(
118  "OutputType",
119  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
121  m_terminalCollectors.ConnectToAggregator("Output",
122  m_aggregator,
123  &MultiFileAggregator::Write1d);
124  break;
125  }
126 
128  // Setup aggregator.
129  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
130  "OutputFileName",
131  StringValue(GetOutputFileName()),
132  "GeneralHeading",
133  StringValue(GetTimeHeading("carrier_id")));
134 
135  // Setup collectors.
136  m_terminalCollectors.SetType("ns3::IntervalRateCollector");
137  m_terminalCollectors.SetAttribute(
138  "InputDataType",
139  EnumValue(IntervalRateCollector::INPUT_DATA_TYPE_UINTEGER));
140  m_terminalCollectors.SetAttribute(
141  "OutputType",
142  EnumValue(IntervalRateCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
143  m_terminalCollectors.SetAttribute("IntervalLength", TimeValue(MilliSeconds(5)));
145  m_terminalCollectors.ConnectToAggregator("OutputWithTime",
146  m_aggregator,
147  &MultiFileAggregator::Write2d);
148  m_terminalCollectors.ConnectToAggregator("OutputString",
149  m_aggregator,
150  &MultiFileAggregator::AddContextHeading);
151  break;
152  }
153 
157  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
158  << " is not a valid output type for this statistics.");
159  break;
160 
163  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
164  << " is not a valid output type for this statistics.");
165  break;
166 
168  // Setup aggregator.
169  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
170  "OutputPath",
171  StringValue(GetOutputPath()),
172  "OutputFileName",
173  StringValue(GetName()));
174  Ptr<MagisterGnuplotAggregator> plotAggregator =
175  m_aggregator->GetObject<MagisterGnuplotAggregator>();
176  NS_ASSERT(plotAggregator != nullptr);
177  // plot->SetTitle ("");
178  plotAggregator->SetLegend("Time (in seconds)", "Correlations");
179  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
180 
181  // Setup collectors.
182  m_terminalCollectors.SetType("ns3::IntervalRateCollector");
183  m_terminalCollectors.SetAttribute(
184  "InputDataType",
185  EnumValue(IntervalRateCollector::INPUT_DATA_TYPE_UINTEGER));
186  m_terminalCollectors.SetAttribute(
187  "OutputType",
188  EnumValue(IntervalRateCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
190  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
191  it != m_terminalCollectors.End();
192  ++it)
193  {
194  const std::string context = it->second->GetName();
195  plotAggregator->Add2dDataset(context, context);
196  }
197  m_terminalCollectors.ConnectToAggregator("OutputWithTime",
198  m_aggregator,
199  &MagisterGnuplotAggregator::Write2d);
200  break;
201  }
202 
206  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
207  << " is not a valid output type for this statistics.");
208  break;
209 
210  default:
211  NS_FATAL_ERROR("SatStatsCarrierIdHelper - Invalid output type");
212  break;
213  }
214 
215  // Create a map of UT addresses and identifiers.
216  NodeContainer uts = GetSatHelper()->GetBeamHelper()->GetUtNodes();
217  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
218  {
220  }
221 
222  // Connect to trace sources at GW nodes.
223 
224  NodeContainer gws = GetSatHelper()->GetBeamHelper()->GetGwNodes();
225  Callback<void, uint32_t, const Address&> callback =
227 
228  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
229  {
230  NetDeviceContainer devs = GetGwSatNetDevice(*it);
231 
232  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
233  {
234  Ptr<SatNetDevice> satDev = (*itDev)->GetObject<SatNetDevice>();
235  NS_ASSERT(satDev != nullptr);
236  Ptr<SatPhy> satPhy = satDev->GetPhy();
237  NS_ASSERT(satPhy != nullptr);
238  Ptr<SatPhyRx> satPhyRx = satPhy->GetPhyRx();
239  NS_ASSERT(satPhyRx != nullptr);
240  ObjectVectorValue carriers;
241  satPhyRx->GetAttribute("RxCarrierList", carriers);
242  NS_LOG_DEBUG(this << " Node ID " << (*it)->GetId() << " device #"
243  << (*itDev)->GetIfIndex() << " has " << carriers.GetN()
244  << " RX carriers");
245 
246  for (ObjectVectorValue::Iterator itCarrier = carriers.Begin();
247  itCarrier != carriers.End();
248  ++itCarrier)
249  {
250  Ptr<SatPhyRxCarrierPerSlot> c =
251  DynamicCast<SatPhyRxCarrierPerSlot>(itCarrier->second);
252  if (!c)
253  {
254  continue;
255  }
256 
258  DynamicCast<SatPhyRxCarrier>(itCarrier->second)->GetCarrierType();
259  if (ct != GetValidCarrierType())
260  {
261  continue;
262  }
263 
264  const bool ret =
265  itCarrier->second->TraceConnectWithoutContext(GetTraceSourceName(), callback);
266  if (ret)
267  {
268  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
269  << " device #" << (*itDev)->GetIfIndex() << " RX carrier #"
270  << itCarrier->first);
271  }
272  else
273  {
274  NS_FATAL_ERROR("Error connecting to " << GetTraceSourceName() << " trace source"
275  << " of SatPhyRxCarrier"
276  << " at node ID " << (*it)->GetId()
277  << " device #" << (*itDev)->GetIfIndex()
278  << " RX carrier #" << itCarrier->first);
279  }
280 
281  } // end of `for (ObjectVectorValue::Iterator itCarrier = carriers)`
282 
283  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
284 
285  } // end of `for (NodeContainer::Iterator it = gws)`
286 
287 } // end of `void DoInstall ();`
288 
289 void
290 SatStatsCarrierIdHelper::CarrierIdRxCallback(uint32_t carrierId, const Address& from)
291 {
292  NS_LOG_FUNCTION(this << carrierId << from);
293 
294  if (from.IsInvalid())
295  {
296  NS_LOG_WARN(this << " discarding a packet"
297  << " from statistics collection because of"
298  << " invalid sender address");
299  return;
300  }
301 
302  // Determine the identifier associated with the sender address.
303  std::map<const Address, uint32_t>::const_iterator it = m_identifierMap.find(from);
304 
305  if (it == m_identifierMap.end())
306  {
307  NS_LOG_WARN(this << " discarding a packet"
308  << " from statistics collection because of"
309  << " unknown sender address " << from);
310  return;
311  }
312 
313  // Find the first-level collector with the right identifier.
314  Ptr<DataCollectionObject> collector = m_terminalCollectors.Get(it->second);
315  NS_ASSERT_MSG(collector != nullptr, "Unable to find collector with identifier " << it->second);
316 
317  switch (GetOutputType())
318  {
321  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
322  NS_ASSERT(c != nullptr);
323  c->TraceSinkUinteger32(0, carrierId);
324  break;
325  }
326 
329  Ptr<IntervalRateCollector> c = collector->GetObject<IntervalRateCollector>();
330  NS_ASSERT(c != nullptr);
331  c->TraceSinkUinteger32(0, carrierId);
332  break;
333  }
334 
335  default:
336  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
337  << " is not a valid output type for this statistics.");
338  break;
339  }
340 }
341 
342 void
344 {
345  NS_LOG_FUNCTION(this << utNode->GetId());
346 
347  const SatIdMapper* satIdMapper = Singleton<SatIdMapper>::Get();
348  const Address addr = satIdMapper->GetUtMacWithNode(utNode);
349 
350  if (addr.IsInvalid())
351  {
352  NS_LOG_WARN(this << " Node " << utNode->GetId() << " is not a valid UT");
353  }
354  else
355  {
356  const uint32_t identifier = GetIdentifierForUt(utNode);
357  m_identifierMap[addr] = identifier;
358  NS_LOG_INFO(this << " associated address " << addr << " with identifier " << identifier);
359  }
360 }
361 
362 } // end of namespace ns3
Class for ID-mapper.
Address GetUtMacWithNode(Ptr< Node > utNode) const
SatNetDevice to be utilized in the UT and GW nodes.
CarrierType
Possible carrier types.
std::map< const Address, uint32_t > m_identifierMap
Map of address and the identifier associated with it (for forward link).
SatStatsCarrierIdHelper(Ptr< const SatHelper > satHelper)
SatPhyRxCarrier::CarrierType GetValidCarrierType() const
Get the valid carrier type.
Ptr< DataCollectionObject > m_aggregator
The aggregator created by this helper.
void SetValidCarrierType(SatPhyRxCarrier::CarrierType carrierType)
Set valid carrier type for this statistics helper type.
static TypeId GetTypeId()
inherited from ObjectBase base class
void CarrierIdRxCallback(uint32_t carrierId, const Address &from)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
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.
void SaveAddressAndIdentifier(Ptr< Node > utNode)
Save the address and the proper identifier from the given UT node.
void SetTraceSourceName(std::string traceSourceName)
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 CreateCollectorPerIdentifier(CollectorMap &collectorMap) const
Create one collector instance for each identifier in the simulation.
OutputType_t GetOutputType() const
uint32_t GetIdentifierForUt(Ptr< Node > utNode) const
std::string GetName() const
virtual std::string GetTimeHeading(std::string dataLabel) const
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.