satellite-stats-signalling-load-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-packet-probe.h>
25 #include <ns3/boolean.h>
26 #include <ns3/callback.h>
27 #include <ns3/data-collection-object.h>
28 #include <ns3/enum.h>
29 #include <ns3/interval-rate-collector.h>
30 #include <ns3/log.h>
31 #include <ns3/mac48-address.h>
32 #include <ns3/magister-gnuplot-aggregator.h>
33 #include <ns3/multi-file-aggregator.h>
34 #include <ns3/node-container.h>
35 #include <ns3/packet.h>
36 #include <ns3/probe.h>
37 #include <ns3/satellite-helper.h>
38 #include <ns3/satellite-id-mapper.h>
39 #include <ns3/satellite-net-device.h>
40 #include <ns3/satellite-topology.h>
41 #include <ns3/scalar-collector.h>
42 #include <ns3/singleton.h>
43 #include <ns3/string.h>
44 #include <ns3/unit-conversion-collector.h>
45 
46 #include <map>
47 #include <sstream>
48 #include <string>
49 #include <utility>
50 
51 NS_LOG_COMPONENT_DEFINE("SatStatsSignallingLoadHelper");
52 
53 namespace ns3
54 {
55 
56 NS_OBJECT_ENSURE_REGISTERED(SatStatsSignallingLoadHelper);
57 
59  : SatStatsHelper(satHelper)
60 {
61  NS_LOG_FUNCTION(this << satHelper);
62 }
63 
65 {
66  NS_LOG_FUNCTION(this);
67 }
68 
69 TypeId // static
71 {
72  static TypeId tid = TypeId("ns3::SatStatsSignallingLoadHelper").SetParent<SatStatsHelper>();
73  return tid;
74 }
75 
76 void
78 {
79  NS_LOG_FUNCTION(this);
80 
81  switch (GetOutputType())
82  {
84  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
85  << " is not a valid output type for this statistics.");
86  break;
87 
89  // Setup aggregator.
90  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
91  "OutputFileName",
92  StringValue(GetOutputFileName()),
93  "MultiFileMode",
94  BooleanValue(false),
95  "EnableContextPrinting",
96  BooleanValue(true),
97  "GeneralHeading",
98  StringValue(GetIdentifierHeading("signalling_kbps")));
99 
100  // Setup second-level collectors.
101  m_terminalCollectors.SetType("ns3::ScalarCollector");
102  m_terminalCollectors.SetAttribute("InputDataType",
103  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
104  m_terminalCollectors.SetAttribute(
105  "OutputType",
106  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SECOND));
108  m_terminalCollectors.ConnectToAggregator("Output",
109  m_aggregator,
110  &MultiFileAggregator::Write1d);
111 
112  // Setup first-level collectors.
113  m_conversionCollectors.SetType("ns3::UnitConversionCollector");
114  m_conversionCollectors.SetAttribute("ConversionType",
115  EnumValue(UnitConversionCollector::FROM_BYTES_TO_KBIT));
117  m_conversionCollectors.ConnectToCollector("Output",
119  &ScalarCollector::TraceSinkDouble);
120  break;
121  }
122 
124  // Setup aggregator.
125  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
126  "OutputFileName",
127  StringValue(GetOutputFileName()),
128  "GeneralHeading",
129  StringValue(GetTimeHeading("signalling_kbps")));
130 
131  // Setup second-level collectors.
132  m_terminalCollectors.SetType("ns3::IntervalRateCollector");
133  m_terminalCollectors.SetAttribute("InputDataType",
134  EnumValue(IntervalRateCollector::INPUT_DATA_TYPE_DOUBLE));
136  m_terminalCollectors.ConnectToAggregator("OutputWithTime",
137  m_aggregator,
138  &MultiFileAggregator::Write2d);
139  m_terminalCollectors.ConnectToAggregator("OutputString",
140  m_aggregator,
141  &MultiFileAggregator::AddContextHeading);
142 
143  // Setup first-level collectors.
144  m_conversionCollectors.SetType("ns3::UnitConversionCollector");
145  m_conversionCollectors.SetAttribute("ConversionType",
146  EnumValue(UnitConversionCollector::FROM_BYTES_TO_KBIT));
148  m_conversionCollectors.ConnectToCollector("Output",
150  &IntervalRateCollector::TraceSinkDouble);
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)", "Signalling load (in kilobits per second)");
179  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
180 
181  // Setup second-level collectors.
182  m_terminalCollectors.SetType("ns3::IntervalRateCollector");
183  m_terminalCollectors.SetAttribute("InputDataType",
184  EnumValue(IntervalRateCollector::INPUT_DATA_TYPE_DOUBLE));
186  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
187  it != m_terminalCollectors.End();
188  ++it)
189  {
190  const std::string context = it->second->GetName();
191  plotAggregator->Add2dDataset(context, context);
192  }
193  m_terminalCollectors.ConnectToAggregator("OutputWithTime",
194  m_aggregator,
195  &MagisterGnuplotAggregator::Write2d);
196 
197  // Setup first-level collectors.
198  m_conversionCollectors.SetType("ns3::UnitConversionCollector");
199  m_conversionCollectors.SetAttribute("ConversionType",
200  EnumValue(UnitConversionCollector::FROM_BYTES_TO_KBIT));
202  m_conversionCollectors.ConnectToCollector("Output",
204  &IntervalRateCollector::TraceSinkDouble);
205  break;
206  }
207 
211  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
212  << " is not a valid output type for this statistics.");
213  break;
214 
215  default:
216  NS_FATAL_ERROR("SatStatsSignallingLoadHelper - Invalid output type");
217  break;
218  }
219 
220  // Setup probes and connect them to conversion collectors.
221  InstallProbes();
222 
223 } // end of `void DoInstall ();`
224 
225 void
227 {
228  NS_LOG_FUNCTION(this);
229 
230  // The method below is supposed to be implemented by the child class.
231  DoInstallProbes();
232 }
233 
234 void
235 SatStatsSignallingLoadHelper::SignallingTxCallback(Ptr<const Packet> packet, const Address& to)
236 {
237  // NS_LOG_FUNCTION (this << packet->GetSize () << from);
238 
239  if (to.IsInvalid())
240  {
241  NS_LOG_WARN(this << " discarding packet " << packet << " (" << packet->GetSize()
242  << " bytes)"
243  << " from statistics collection because of"
244  << " invalid sender address");
245  }
246  else
247  {
248  const Mac48Address addr = Mac48Address::ConvertFrom(to);
249 
250  if (addr.IsBroadcast())
251  {
252  NS_LOG_INFO(this << " broadcast control message packet");
253 
254  // Pass the sample to every first-level collectors.
255  for (CollectorMap::Iterator it = m_conversionCollectors.Begin();
256  it != m_conversionCollectors.End();
257  ++it)
258  {
259  Ptr<UnitConversionCollector> c = it->second->GetObject<UnitConversionCollector>();
260  NS_ASSERT(c != nullptr);
261  c->TraceSinkUinteger32(0, packet->GetSize());
262  }
263  }
264  else
265  {
266  // Determine the identifier associated with the sender address.
267  std::map<const Address, uint32_t>::const_iterator it = m_identifierMap.find(addr);
268 
269  if (it == m_identifierMap.end())
270  {
271  NS_LOG_WARN(this << " discarding packet " << packet << " (" << packet->GetSize()
272  << " bytes)"
273  << " from statistics collection because of"
274  << " unknown sender address " << addr);
275  }
276  else
277  {
278  // Find the first-level collector with the right identifier.
279  Ptr<DataCollectionObject> collector = m_conversionCollectors.Get(it->second);
280  NS_ASSERT_MSG(collector != nullptr,
281  "Unable to find collector with identifier " << it->second);
282  Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
283  NS_ASSERT(c != nullptr);
284 
285  // Pass the sample to the collector.
286  c->TraceSinkUinteger32(0, packet->GetSize());
287  }
288  }
289  }
290 
291 } // end of `void RxCallback (Ptr<const Packet>, const Address);`
292 
293 // FORWARD LINK ///////////////////////////////////////////////////////////////
294 
295 NS_OBJECT_ENSURE_REGISTERED(SatStatsFwdSignallingLoadHelper);
296 
298  : SatStatsSignallingLoadHelper(satHelper)
299 {
300  NS_LOG_FUNCTION(this << satHelper);
301 }
302 
304 {
305  NS_LOG_FUNCTION(this);
306 }
307 
308 TypeId // static
310 {
311  static TypeId tid =
312  TypeId("ns3::SatStatsFwdSignallingLoadHelper").SetParent<SatStatsSignallingLoadHelper>();
313  return tid;
314 }
315 
316 void
318 {
319  NS_LOG_FUNCTION(this);
320 
321  // Create a map of UT addresses and identifiers.
322  NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
323  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
324  {
326  }
327 
328  // Connect to trace sources at GW nodes.
329 
330  NodeContainer gws = Singleton<SatTopology>::Get()->GetGwNodes();
331  Callback<void, Ptr<const Packet>, const Address&> callback =
333 
334  for (NodeContainer::Iterator it = gws.Begin(); it != gws.End(); ++it)
335  {
336  NetDeviceContainer devs = GetGwSatNetDevice(*it);
337 
338  for (NetDeviceContainer::Iterator itDev = devs.Begin(); itDev != devs.End(); ++itDev)
339  {
340  NS_ASSERT((*itDev)->GetObject<SatNetDevice>() != nullptr);
341 
342  if ((*itDev)->TraceConnectWithoutContext("SignallingTx", callback))
343  {
344  NS_LOG_INFO(this << " successfully connected with node ID " << (*it)->GetId()
345  << " device #" << (*itDev)->GetIfIndex());
346  }
347  else
348  {
349  NS_FATAL_ERROR("Error connecting to SignallingTx trace source"
350  << " of SatNetDevice"
351  << " at node ID " << (*it)->GetId() << " device #"
352  << (*itDev)->GetIfIndex());
353  }
354 
355  } // end of `for (NetDeviceContainer::Iterator itDev = devs)`
356 
357  } // end of `for (NodeContainer::Iterator it = gws)`
358 
359 } // end of `void DoInstallProbes ();`
360 
361 // RETURN LINK ////////////////////////////////////////////////////////////////
362 
363 NS_OBJECT_ENSURE_REGISTERED(SatStatsRtnSignallingLoadHelper);
364 
366  : SatStatsSignallingLoadHelper(satHelper)
367 {
368  NS_LOG_FUNCTION(this << satHelper);
369 }
370 
372 {
373  NS_LOG_FUNCTION(this);
374 }
375 
376 TypeId // static
378 {
379  static TypeId tid =
380  TypeId("ns3::SatStatsRtnSignallingLoadHelper").SetParent<SatStatsSignallingLoadHelper>();
381  return tid;
382 }
383 
384 void
386 {
387  NS_LOG_FUNCTION(this);
388  NodeContainer uts = Singleton<SatTopology>::Get()->GetUtNodes();
389 
390  for (NodeContainer::Iterator it = uts.Begin(); it != uts.End(); ++it)
391  {
392  const int32_t utId = GetUtId(*it);
393  NS_ASSERT_MSG(utId > 0, "Node " << (*it)->GetId() << " is not a valid UT");
394  const uint32_t identifier = GetIdentifierForUt(*it);
395 
396  // Create the probe.
397  std::ostringstream probeName;
398  probeName << utId;
399  Ptr<ApplicationPacketProbe> probe = CreateObject<ApplicationPacketProbe>();
400  probe->SetName(probeName.str());
401 
402  Ptr<NetDevice> dev = GetUtSatNetDevice(*it);
403 
404  // Connect the object to the probe.
405  if (probe->ConnectByObject("SignallingTx", dev))
406  {
407  // Connect the probe to the right collector.
408  if (m_conversionCollectors.ConnectWithProbe(
409  probe->GetObject<Probe>(),
410  "OutputBytes",
411  identifier,
412  &UnitConversionCollector::TraceSinkUinteger32))
413  {
414  NS_LOG_INFO(this << " created probe " << probeName.str()
415  << ", connected to collector " << identifier);
416  m_probes.insert(
417  std::make_pair(probe->GetObject<Probe>(), std::make_pair(*it, identifier)));
418  }
419  else
420  {
421  NS_LOG_WARN(this << " unable to connect probe " << probeName.str()
422  << " to collector " << identifier);
423  }
424 
425  } // end of `if (probe->ConnectByObject ("SignallingTx", dev))`
426  else
427  {
428  NS_FATAL_ERROR("Error connecting to SignallingTx trace source of SatNetDevice"
429  << " at node ID " << (*it)->GetId() << " device #2");
430  }
431 
432  } // end of `for (it = uts.Begin(); it != uts.End (); ++it)`
433 
434 } // end of `void DoInstallProbes ();`
435 
436 void
438 {
439  NS_LOG_FUNCTION(this);
440 
441  std::map<Ptr<Probe>, std::pair<Ptr<Node>, uint32_t>>::iterator it;
442 
443  for (it = m_probes.begin(); it != m_probes.end(); it++)
444  {
445  Ptr<Probe> probe = it->first;
446  Ptr<Node> node = it->second.first;
447  uint32_t identifier = it->second.second;
448 
449  if (!m_conversionCollectors.DisconnectWithProbe(
450  probe->GetObject<Probe>(),
451  "OutputBytes",
452  identifier,
453  &UnitConversionCollector::TraceSinkUinteger32))
454  {
455  NS_FATAL_ERROR("Error disconnecting trace file on handover");
456  }
457 
458  identifier = GetIdentifierForUtUser(node);
459 
460  if (!m_conversionCollectors.ConnectWithProbe(probe->GetObject<Probe>(),
461  "OutputBytes",
462  identifier,
463  &UnitConversionCollector::TraceSinkUinteger32))
464  {
465  NS_FATAL_ERROR("Error connecting trace file on handover");
466  }
467 
468  it->second.second = identifier;
469  }
470 } // end of `void UpdateIdentifierOnProbes ();`
471 
472 } // end of namespace ns3
SatNetDevice to be utilized in the UT and GW nodes.
Produce forward link signalling load statistics from a satellite module simulation.
SatStatsFwdSignallingLoadHelper(Ptr< const SatHelper > satHelper)
static TypeId GetTypeId()
inherited from ObjectBase base class
Parent abstract class of all satellite statistics helpers.
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)
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
Produce return link signalling load statistics from a satellite module simulation.
SatStatsRtnSignallingLoadHelper(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.
static TypeId GetTypeId()
inherited from ObjectBase base class
virtual void UpdateIdentifierOnProbes()
Change identifier used on probes, when handovers occur.
Abstract class inherited by SatStatsFwdSignallingLoadHelper and SatStatsRtnSignallingLoadHelper.
Ptr< DataCollectionObject > m_aggregator
The aggregator created by this helper.
void DoInstall()
Install the probes, collectors, and aggregators necessary to produce the statistics output.
void InstallProbes()
Set up several probes or other means of listeners and connect them to the first-level collectors.
CollectorMap m_terminalCollectors
Maintains a list of second-level collectors created by this helper.
void SignallingTxCallback(Ptr< const Packet > packet, const Address &to)
Receive inputs from trace sources and determine the right collector to forward the inputs to.
static TypeId GetTypeId()
inherited from ObjectBase base class
SatStatsSignallingLoadHelper(Ptr< const SatHelper > satHelper)
CollectorMap m_conversionCollectors
Maintains a list of first-level collectors created by this helper.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.