A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
radio-bearer-stats-calculator.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
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: Jaume Nin <jnin@cttc.es>
19  */
20 
22 #include "ns3/string.h"
23 #include "ns3/nstime.h"
24 #include <ns3/log.h>
25 #include <vector>
26 #include <algorithm>
27 
28 namespace ns3
29 {
30 
31 NS_LOG_COMPONENT_DEFINE ("RadioBearerStatsCalculator");
32 
33 NS_OBJECT_ENSURE_REGISTERED ( RadioBearerStatsCalculator);
34 
36  : m_firstWrite (true),
37  m_pendingOutput (false),
38  m_protocolType ("RLC")
39 {
40  NS_LOG_FUNCTION (this);
41 }
42 
44  : m_firstWrite (true),
45  m_pendingOutput (false)
46 {
47  NS_LOG_FUNCTION (this);
48  m_protocolType = protocolType;
49 }
50 
52 {
53  NS_LOG_FUNCTION (this);
54 }
55 
56 TypeId
58 {
59  static TypeId tid =
60  TypeId ("ns3::RadioBearerStatsCalculator")
61  .SetParent<LteStatsCalculator> ().AddConstructor<RadioBearerStatsCalculator> ()
62  .AddAttribute ("StartTime", "Start time of the on going epoch.", TimeValue (Seconds (0.)),MakeTimeAccessor (&RadioBearerStatsCalculator::m_startTime), MakeTimeChecker ())
63  .AddAttribute ("EpochDuration", "Epoch duration.", TimeValue (Seconds (0.25)), MakeTimeAccessor (&RadioBearerStatsCalculator::m_epochDuration), MakeTimeChecker ())
64  .AddAttribute ("DlRlcOutputFilename",
65  "Name of the file where the downlink results will be saved.",
66  StringValue ("DlRlcStats.txt"),
67  MakeStringAccessor (&LteStatsCalculator::SetDlOutputFilename),
68  MakeStringChecker ())
69  .AddAttribute ("UlRlcOutputFilename",
70  "Name of the file where the uplink results will be saved.",
71  StringValue ("UlRlcStats.txt"),
72  MakeStringAccessor (&LteStatsCalculator::SetUlOutputFilename),
73  MakeStringChecker ())
74  .AddAttribute ("DlPdcpOutputFilename",
75  "Name of the file where the downlink results will be saved.",
76  StringValue ("DlPdcpStats.txt"),
78  MakeStringChecker ())
79  .AddAttribute ("UlPdcpOutputFilename",
80  "Name of the file where the uplink results will be saved.",
81  StringValue ("UlPdcpStats.txt"),
83  MakeStringChecker ())
84  ;
85  return tid;
86 }
87 
88 void
90 {
91  NS_LOG_FUNCTION (this);
92  if (m_pendingOutput)
93  {
94  ShowResults ();
95  }
96 }
97 
98 void
99 RadioBearerStatsCalculator::UlTxPdu (uint64_t imsi, uint16_t rnti, uint8_t lcid, uint32_t packetSize)
100 {
101  NS_LOG_FUNCTION (this << "UlTxPDU" << imsi << rnti << (uint32_t) lcid << packetSize);
102  CheckEpoch ();
103  ImsiLcidPair_t p (imsi, lcid);
104  if (Simulator::Now () > m_startTime)
105  {
106  m_flowId[p] = LteFlowId_t (rnti, lcid);
107  m_ulTxPackets[p]++;
108  m_ulTxData[p] += packetSize;
109  }
110  m_pendingOutput = true;
111 }
112 
113 void
114 RadioBearerStatsCalculator::DlTxPdu (uint16_t cellId, uint64_t imsi, uint16_t rnti, uint8_t lcid, uint32_t packetSize)
115 {
116  NS_LOG_FUNCTION (this << "DlTxPDU" << imsi << rnti << (uint32_t) lcid << packetSize);
117  CheckEpoch ();
118  ImsiLcidPair_t p (imsi, lcid);
119  if (Simulator::Now () > m_startTime)
120  {
121  m_dlCellId[p] = cellId;
122  m_flowId[p] = LteFlowId_t (rnti, lcid);
123  m_dlTxPackets[p]++;
124  m_dlTxData[p] += packetSize;
125  }
126  m_pendingOutput = true;
127 }
128 
129 void
130 RadioBearerStatsCalculator::UlRxPdu (uint16_t cellId, uint64_t imsi, uint16_t rnti, uint8_t lcid, uint32_t packetSize,
131  uint64_t delay)
132 {
133  NS_LOG_FUNCTION (this << "UlRxPDU" << imsi << rnti << (uint32_t) lcid << packetSize << delay);
134  ImsiLcidPair_t p (imsi, lcid);
135  CheckEpoch ();
136 
137  if (Simulator::Now () > m_startTime)
138  {
139  m_ulCellId[p] = cellId;
140  m_ulRxPackets[p]++;
141  m_ulRxData[p] += packetSize;
142 
143  Uint64StatsMap::iterator it = m_ulDelay.find (p);
144  if (it == m_ulDelay.end ())
145  {
146  NS_LOG_DEBUG (this << " Creating UL stats calculators for IMSI " << p.m_imsi << " and LCID " << (uint32_t) p.m_lcId);
147  m_ulDelay[p] = CreateObject<MinMaxAvgTotalCalculator<uint64_t> > ();
148  m_ulPduSize[p] = CreateObject<MinMaxAvgTotalCalculator<uint32_t> > ();
149  }
150  m_ulDelay[p]->Update (delay);
151  m_ulPduSize[p]->Update (packetSize);
152  }
153  m_pendingOutput = true;
154 }
155 
156 void
157 RadioBearerStatsCalculator::DlRxPdu (uint64_t imsi, uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
158 {
159  NS_LOG_FUNCTION (this << "DlRxPDU" << imsi << rnti << (uint32_t) lcid << packetSize << delay);
160  CheckEpoch ();
161  ImsiLcidPair_t p (imsi, lcid);
162  if (Simulator::Now () > m_startTime)
163  {
164  m_dlRxPackets[p]++;
165  m_dlRxData[p] += packetSize;
166 
167  Uint64StatsMap::iterator it = m_dlDelay.find (p);
168  if (it == m_dlDelay.end ())
169  {
170  NS_LOG_DEBUG (this << " Creating DL stats calculators for IMSI " << p.m_imsi << " and LCID " << (uint32_t) p.m_lcId);
171  m_dlDelay[p] = CreateObject<MinMaxAvgTotalCalculator<uint64_t> > ();
172  m_dlPduSize[p] = CreateObject<MinMaxAvgTotalCalculator<uint32_t> > ();
173  }
174  m_dlDelay[p]->Update (delay);
175  m_dlPduSize[p]->Update (packetSize);
176  }
177  m_pendingOutput = true;
178 }
179 
180 void
182 {
183 
184  NS_LOG_FUNCTION (this << GetUlOutputFilename ().c_str () << GetDlOutputFilename ().c_str ());
185  NS_LOG_INFO ("Write Rlc Stats in " << GetUlOutputFilename ().c_str () << " and in " << GetDlOutputFilename ().c_str ());
186 
187  std::ofstream ulOutFile;
188  std::ofstream dlOutFile;
189 
190  if (m_firstWrite == true)
191  {
192  ulOutFile.open (GetUlOutputFilename ().c_str ());
193  if (!ulOutFile.is_open ())
194  {
195  NS_LOG_ERROR ("Can't open file " << GetUlOutputFilename ().c_str ());
196  return;
197  }
198 
199  dlOutFile.open (GetDlOutputFilename ().c_str ());
200  if (!dlOutFile.is_open ())
201  {
202  NS_LOG_ERROR ("Can't open file " << GetDlOutputFilename ().c_str ());
203  return;
204  }
205  m_firstWrite = false;
206  ulOutFile << "% start\tend\tCellId\tIMSI\tRNTI\tLCID\tnTxPDUs\tTxBytes\tnRxPDUs\tRxBytes\t";
207  ulOutFile << "delay\tstdDev\tmin\tmax\t";
208  ulOutFile << "PduSize\tstdDev\tmin\tmax";
209  ulOutFile << std::endl;
210  dlOutFile << "% start\tend\tCellId\tIMSI\tRNTI\tLCID\tnTxPDUs\tTxBytes\tnRxPDUs\tRxBytes\t";
211  dlOutFile << "delay\tstdDev\tmin\tmax\t";
212  dlOutFile << "PduSize\tstdDev\tmin\tmax";
213  dlOutFile << std::endl;
214  }
215  else
216  {
217  ulOutFile.open (GetUlOutputFilename ().c_str (), std::ios_base::app);
218  if (!ulOutFile.is_open ())
219  {
220  NS_LOG_ERROR ("Can't open file " << GetUlOutputFilename ().c_str ());
221  return;
222  }
223 
224  dlOutFile.open (GetDlOutputFilename ().c_str (), std::ios_base::app);
225  if (!dlOutFile.is_open ())
226  {
227  NS_LOG_ERROR ("Can't open file " << GetDlOutputFilename ().c_str ());
228  return;
229  }
230  }
231 
232  WriteUlResults (ulOutFile);
233  WriteDlResults (dlOutFile);
234  m_pendingOutput = false;
235 
236 }
237 
238 void
240 {
241  NS_LOG_FUNCTION (this);
242 
243  // Get the unique IMSI / LCID list
244 
245  std::vector < ImsiLcidPair_t > pairVector;
246  for (Uint32Map::iterator it = m_ulTxPackets.begin (); it != m_ulTxPackets.end (); ++it)
247  {
248  if (find (pairVector.begin (), pairVector.end (), (*it).first) == pairVector.end ())
249  {
250  pairVector.push_back ((*it).first);
251  }
252  }
253 
254  Time endTime = m_startTime + m_epochDuration;
255  for (std::vector<ImsiLcidPair_t>::iterator it = pairVector.begin (); it != pairVector.end (); ++it)
256  {
257  ImsiLcidPair_t p = *it;
258  outFile << m_startTime.GetNanoSeconds () / 1.0e9 << "\t";
259  outFile << endTime.GetNanoSeconds () / 1.0e9 << "\t";
260  outFile << GetUlCellId (p.m_imsi, p.m_lcId) << "\t";
261  outFile << p.m_imsi << "\t";
262  outFile << m_flowId[p].m_rnti << "\t";
263  outFile << (uint32_t) m_flowId[p].m_lcId << "\t";
264  outFile << GetUlTxPackets (p.m_imsi, p.m_lcId) << "\t";
265  outFile << GetUlTxData (p.m_imsi, p.m_lcId) << "\t";
266  outFile << GetUlRxPackets (p.m_imsi, p.m_lcId) << "\t";
267  outFile << GetUlRxData (p.m_imsi, p.m_lcId) << "\t";
268  std::vector<double> stats = GetUlDelayStats (p.m_imsi, p.m_lcId);
269  for (std::vector<double>::iterator it = stats.begin (); it != stats.end (); ++it)
270  {
271  outFile << (*it) * 1e-9 << "\t";
272  }
273  stats = GetUlPduSizeStats (p.m_imsi, p.m_lcId);
274  for (std::vector<double>::iterator it = stats.begin (); it != stats.end (); ++it)
275  {
276  outFile << (*it) << "\t";
277  }
278  outFile << std::endl;
279  }
280 
281  outFile.close ();
282 }
283 
284 void
286 {
287  NS_LOG_FUNCTION (this);
288 
289  // Get the unique IMSI list
290  std::vector < ImsiLcidPair_t > pairVector;
291  for (Uint32Map::iterator it = m_dlTxPackets.begin (); it != m_dlTxPackets.end (); ++it)
292  {
293  if (find (pairVector.begin (), pairVector.end (), (*it).first) == pairVector.end ())
294  {
295  pairVector.push_back ((*it).first);
296  }
297  }
298 
299  Time endTime = m_startTime + m_epochDuration;
300  for (std::vector<ImsiLcidPair_t>::iterator pair = pairVector.begin (); pair != pairVector.end (); ++pair)
301  {
302  ImsiLcidPair_t p = *pair;
303  outFile << m_startTime.GetNanoSeconds () / 1.0e9 << "\t";
304  outFile << endTime.GetNanoSeconds () / 1.0e9 << "\t";
305  outFile << GetDlCellId (p.m_imsi, p.m_lcId) << "\t";
306  outFile << p.m_imsi << "\t";
307  outFile << m_flowId[p].m_rnti << "\t";
308  outFile << (uint32_t) m_flowId[p].m_lcId << "\t";
309  outFile << GetDlTxPackets (p.m_imsi, p.m_lcId) << "\t";
310  outFile << GetDlTxData (p.m_imsi, p.m_lcId) << "\t";
311  outFile << GetDlRxPackets (p.m_imsi, p.m_lcId) << "\t";
312  outFile << GetDlRxData (p.m_imsi, p.m_lcId) << "\t";
313  std::vector<double> stats = GetDlDelayStats (p.m_imsi, p.m_lcId);
314  for (std::vector<double>::iterator it = stats.begin (); it != stats.end (); ++it)
315  {
316  outFile << (*it) * 1e-9 << "\t";
317  }
318  stats = GetDlPduSizeStats (p.m_imsi, p.m_lcId);
319  for (std::vector<double>::iterator it = stats.begin (); it != stats.end (); ++it)
320  {
321  outFile << (*it) << "\t";
322  }
323  outFile << std::endl;
324  }
325 
326  outFile.close ();
327 }
328 
329 void
331 {
332  NS_LOG_FUNCTION (this);
333 
334  m_ulTxPackets.erase (m_ulTxPackets.begin (), m_ulTxPackets.end ());
335  m_ulRxPackets.erase (m_ulRxPackets.begin (), m_ulRxPackets.end ());
336  m_ulRxData.erase (m_ulRxData.begin (), m_ulRxData.end ());
337  m_ulTxData.erase (m_ulTxData.begin (), m_ulTxData.end ());
338  m_ulDelay.erase (m_ulDelay.begin (), m_ulDelay.end ());
339  m_ulPduSize.erase (m_ulPduSize.begin (), m_ulPduSize.end ());
340 
341  m_dlTxPackets.erase (m_dlTxPackets.begin (), m_dlTxPackets.end ());
342  m_dlRxPackets.erase (m_dlRxPackets.begin (), m_dlRxPackets.end ());
343  m_dlRxData.erase (m_dlRxData.begin (), m_dlRxData.end ());
344  m_dlTxData.erase (m_dlTxData.begin (), m_dlTxData.end ());
345  m_dlDelay.erase (m_dlDelay.begin (), m_dlDelay.end ());
346  m_dlPduSize.erase (m_dlPduSize.begin (), m_dlPduSize.end ());
347 }
348 
349 void
351 {
352  NS_LOG_FUNCTION (this);
353 
355  {
356  ShowResults ();
357  ResetResults ();
358  StartEpoch ();
359  }
360 }
361 
362 void
364 {
365  NS_LOG_FUNCTION (this);
367  {
369  }
370 }
371 
372 uint32_t
373 RadioBearerStatsCalculator::GetUlTxPackets (uint64_t imsi, uint8_t lcid)
374 {
375  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
376  ImsiLcidPair_t p (imsi, lcid);
377  return m_ulTxPackets[p];
378 }
379 
380 uint32_t
381 RadioBearerStatsCalculator::GetUlRxPackets (uint64_t imsi, uint8_t lcid)
382 {
383  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
384  ImsiLcidPair_t p (imsi, lcid);
385  return m_ulRxPackets[p];
386 }
387 
388 uint64_t
389 RadioBearerStatsCalculator::GetUlTxData (uint64_t imsi, uint8_t lcid)
390 {
391  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
392  ImsiLcidPair_t p (imsi, lcid);
393  return m_ulTxData[p];
394 }
395 
396 uint64_t
397 RadioBearerStatsCalculator::GetUlRxData (uint64_t imsi, uint8_t lcid)
398 {
399  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
400  ImsiLcidPair_t p (imsi, lcid);
401  return m_ulRxData[p];
402 }
403 
404 double
405 RadioBearerStatsCalculator::GetUlDelay (uint64_t imsi, uint8_t lcid)
406 {
407  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
408  ImsiLcidPair_t p (imsi, lcid);
409  Uint64StatsMap::iterator it = m_ulDelay.find (p);
410  if (it == m_ulDelay.end ())
411  {
412  NS_LOG_ERROR ("UL delay for " << imsi << " - " << (uint16_t) lcid << " not found");
413  return 0;
414 
415  }
416  return m_ulDelay[p]->getMean ();
417 }
418 
419 std::vector<double>
420 RadioBearerStatsCalculator::GetUlDelayStats (uint64_t imsi, uint8_t lcid)
421 {
422  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
423  ImsiLcidPair_t p (imsi, lcid);
424  std::vector<double> stats;
425  Uint64StatsMap::iterator it = m_ulDelay.find (p);
426  if (it == m_ulDelay.end ())
427  {
428  stats.push_back (0.0);
429  stats.push_back (0.0);
430  stats.push_back (0.0);
431  stats.push_back (0.0);
432  return stats;
433 
434  }
435  stats.push_back (m_ulDelay[p]->getMean ());
436  stats.push_back (m_ulDelay[p]->getStddev ());
437  stats.push_back (m_ulDelay[p]->getMin ());
438  stats.push_back (m_ulDelay[p]->getMax ());
439  return stats;
440 }
441 
442 std::vector<double>
444 {
445  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
446  ImsiLcidPair_t p (imsi, lcid);
447  std::vector<double> stats;
448  Uint32StatsMap::iterator it = m_ulPduSize.find (p);
449  if (it == m_ulPduSize.end ())
450  {
451  stats.push_back (0.0);
452  stats.push_back (0.0);
453  stats.push_back (0.0);
454  stats.push_back (0.0);
455  return stats;
456 
457  }
458  stats.push_back (m_ulPduSize[p]->getMean ());
459  stats.push_back (m_ulPduSize[p]->getStddev ());
460  stats.push_back (m_ulPduSize[p]->getMin ());
461  stats.push_back (m_ulPduSize[p]->getMax ());
462  return stats;
463 }
464 
465 uint32_t
466 RadioBearerStatsCalculator::GetDlTxPackets (uint64_t imsi, uint8_t lcid)
467 {
468  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
469  ImsiLcidPair_t p (imsi, lcid);
470  return m_dlTxPackets[p];
471 }
472 
473 uint32_t
474 RadioBearerStatsCalculator::GetDlRxPackets (uint64_t imsi, uint8_t lcid)
475 {
476  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
477  ImsiLcidPair_t p (imsi, lcid);
478  return m_dlRxPackets[p];
479 }
480 
481 uint64_t
482 RadioBearerStatsCalculator::GetDlTxData (uint64_t imsi, uint8_t lcid)
483 {
484  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
485  ImsiLcidPair_t p (imsi, lcid);
486  return m_dlTxData[p];
487 }
488 
489 uint64_t
490 RadioBearerStatsCalculator::GetDlRxData (uint64_t imsi, uint8_t lcid)
491 {
492  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
493  ImsiLcidPair_t p (imsi, lcid);
494  return m_dlRxData[p];
495 }
496 
497 uint32_t
498 RadioBearerStatsCalculator::GetUlCellId (uint64_t imsi, uint8_t lcid)
499 {
500  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
501  ImsiLcidPair_t p (imsi, lcid);
502  return m_ulCellId[p];
503 }
504 
505 uint32_t
506 RadioBearerStatsCalculator::GetDlCellId (uint64_t imsi, uint8_t lcid)
507 {
508  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
509  ImsiLcidPair_t p (imsi, lcid);
510  return m_dlCellId[p];
511 }
512 
513 double
514 RadioBearerStatsCalculator::GetDlDelay (uint64_t imsi, uint8_t lcid)
515 {
516  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
517  ImsiLcidPair_t p (imsi, lcid);
518  Uint64StatsMap::iterator it = m_dlDelay.find (p);
519  if (it == m_dlDelay.end ())
520  {
521  NS_LOG_ERROR ("DL delay for " << imsi << " not found");
522  return 0;
523  }
524  return m_dlDelay[p]->getMean ();
525 }
526 
527 std::vector<double>
528 RadioBearerStatsCalculator::GetDlDelayStats (uint64_t imsi, uint8_t lcid)
529 {
530  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
531  ImsiLcidPair_t p (imsi, lcid);
532  std::vector<double> stats;
533  Uint64StatsMap::iterator it = m_dlDelay.find (p);
534  if (it == m_dlDelay.end ())
535  {
536  stats.push_back (0.0);
537  stats.push_back (0.0);
538  stats.push_back (0.0);
539  stats.push_back (0.0);
540  return stats;
541 
542  }
543  stats.push_back (m_dlDelay[p]->getMean ());
544  stats.push_back (m_dlDelay[p]->getStddev ());
545  stats.push_back (m_dlDelay[p]->getMin ());
546  stats.push_back (m_dlDelay[p]->getMax ());
547  return stats;
548 }
549 
550 std::vector<double>
552 {
553  NS_LOG_FUNCTION (this << imsi << (uint16_t) lcid);
554  ImsiLcidPair_t p (imsi, lcid);
555  std::vector<double> stats;
556  Uint32StatsMap::iterator it = m_dlPduSize.find (p);
557  if (it == m_dlPduSize.end ())
558  {
559  stats.push_back (0.0);
560  stats.push_back (0.0);
561  stats.push_back (0.0);
562  stats.push_back (0.0);
563  return stats;
564 
565  }
566  stats.push_back (m_dlPduSize[p]->getMean ());
567  stats.push_back (m_dlPduSize[p]->getStddev ());
568  stats.push_back (m_dlPduSize[p]->getMin ());
569  stats.push_back (m_dlPduSize[p]->getMax ());
570  return stats;
571 }
572 
573 std::string
575 {
576  if (m_protocolType == "RLC")
577  {
579  }
580  else
581  {
582  return GetUlPdcpOutputFilename ();
583  }
584 }
585 
586 std::string
588 {
589  if (m_protocolType == "RLC")
590  {
592  }
593  else
594  {
595  return GetDlPdcpOutputFilename ();
596  }
597 }
598 
599 void
601 {
602  m_ulPdcpOutputFilename = outputFilename;
603 }
604 
605 std::string
607 {
608  return m_ulPdcpOutputFilename;
609 }
610 void
612 {
613  m_dlPdcpOutputFilename = outputFilename;
614 }
615 
616 std::string
618 {
619  return m_dlPdcpOutputFilename;
620 }
621 
622 } // namespace ns3