Fixed throughput calculation
authorjnin
Mon, 04 Apr 2011 18:17:17 +0200
changeset 7941 c92f27568aef
parent 7940 50dd9246e780
child 7942 c0036edce3a5
Fixed throughput calculation Fixed output format to be compliant with Requirements Document
src/lte/helper/rlc-stats-calculator.cc
src/lte/helper/rlc-stats-calculator.h
--- a/src/lte/helper/rlc-stats-calculator.cc	Fri Apr 01 12:02:18 2011 +0200
+++ b/src/lte/helper/rlc-stats-calculator.cc	Mon Apr 04 18:17:17 2011 +0200
@@ -22,6 +22,8 @@
 #include "ns3/string.h"
 #include "ns3/nstime.h"
 #include <ns3/log.h>
+#include <vector>
+#include <algorithm>
 
 namespace ns3 {
 
@@ -30,7 +32,8 @@
 NS_OBJECT_ENSURE_REGISTERED (RlcStatsCalculator);
 
 RlcStatsCalculator::RlcStatsCalculator() :
-    m_outputFilename ("")
+    m_outputFilename (""),
+    m_firstWrite(true)
 {
   NS_LOG_FUNCTION (this);
 
@@ -53,6 +56,15 @@
                    StringValue ("RlcStats.csv"),
                    MakeStringAccessor (&RlcStatsCalculator::SetOutputFilename),
                    MakeStringChecker ())
+    .AddAttribute ("StartTime",
+                   "Start time of the on going epoch.",
+                   TimeValue ( Seconds(0.) ),
+                   MakeTimeAccessor (&RlcStatsCalculator::m_startTime),
+                   MakeTimeChecker ())
+    .AddAttribute("EpochDuration",
+                  "Epoch duration.", TimeValue(Seconds(0.25)),
+                  MakeTimeAccessor(&RlcStatsCalculator::m_epochDuration),
+                  MakeTimeChecker())
     ;
   return tid;
 }
@@ -67,81 +79,117 @@
 RlcStatsCalculator::TxPdu (uint16_t rnti, uint8_t lcid, uint32_t packetSize)
 {
   NS_LOG_FUNCTION (this << "TxPDU" << rnti << (uint32_t) lcid << packetSize);
-  lteFlowId_t pair (rnti, lcid);
-
-  m_txPackets[pair]++;
+  if (Simulator::Now () > m_startTime )
+    {
+      lteFlowId_t pair (rnti, lcid);
+      m_txPackets[pair]++;
+    }
+  CheckEpoch ();
 }
 
 void
 RlcStatsCalculator::RxPdu (uint16_t rnti, uint8_t lcid, uint32_t packetSize, uint64_t delay)
 {
   NS_LOG_FUNCTION (this << "RxPDU" << rnti << (uint32_t) lcid << packetSize << delay);
-  lteFlowId_t pair (rnti, lcid);
-
-  m_rxPackets [pair]++;
-  m_rxData [pair] += packetSize;
+  if (Simulator::Now () > m_startTime )
+    {
+      lteFlowId_t pair(rnti, lcid);
+      m_rxPackets[pair]++;
+      m_rxData[pair] += packetSize;
+      m_throughput[pair] = 8 * m_rxData[pair] / 1.0e9 * (Simulator::Now().GetNanoSeconds() - m_startTime.GetNanoSeconds());
 
-  uint64StatsMap::iterator it = m_delay.find (pair);
-  if ( it == m_delay.end () )
-    {
-      m_delay[pair] = CreateObject <MinMaxAvgTotalCalculator<uint64_t> > ();
+      uint64StatsMap::iterator it = m_delay.find(pair);
+      if (it == m_delay.end())
+        {
+          m_delay[pair] = CreateObject<MinMaxAvgTotalCalculator<uint64_t> > ();
+          }
+      m_delay[pair]->Update(delay);
     }
-  m_delay[pair]->Update (delay);
+  CheckEpoch ();
 }
 
 void
 RlcStatsCalculator::ShowResults (void)
 {
   uint32Map::iterator it;
-  uint64Map::iterator itData;
-  uint64StatsMap::iterator itDelay;
+
 
   NS_LOG_FUNCTION (this <<  m_outputFilename.c_str ());
   NS_LOG_INFO ("Write Rlc Stats in: " << m_outputFilename.c_str ());
   
   std::ofstream m_outFile;
-  m_outFile.open (m_outputFilename.c_str ());
-  if (! m_outFile.is_open ())
-  {
-    NS_LOG_ERROR ("Can't open file " << m_outputFilename.c_str ());
-    return;
-  }
+  if ( m_firstWrite == true )
+    {
+      m_outFile.open (m_outputFilename.c_str ());
+      if (! m_outFile.is_open ())
+      {
+        NS_LOG_ERROR ("Can't open file " << m_outputFilename.c_str ());
+        return;
+      }
+      m_firstWrite = false;
+      m_outFile << "# startTime, endTime, RNTI, LCID, throughput (bps), delay (s), PDU loss ratio (%)" << std::endl;
+    }
+  else
+    {
+      m_outFile.open (m_outputFilename.c_str (),  std::ios_base::app);
+      if (! m_outFile.is_open ())
+      {
+        NS_LOG_ERROR ("Can't open file " << m_outputFilename.c_str ());
+        return;
+      }
+    }
 
-  m_outFile << "# Parameter, RNTI, LCID, value" << std::endl;
+
+
+  // Get all the unique lteFlowIds in the calculator
+  std::vector<lteFlowId_t> lteFlowIds;
   for ( it = m_txPackets.begin(); it != m_txPackets.end(); ++it)
     {
-      m_outFile << "TxPackets, " << (*it).first.m_rnti << ", "
-                                 << (uint32_t) (*it).first.m_lcId << ", "
-                                 << (*it).second << std::endl;
-    }
-  for ( it = m_rxPackets.begin(); it != m_rxPackets.end(); ++it)
-    {
-      m_outFile << "RxPackets, " << (*it).first.m_rnti << ", "
-                                 << (uint32_t) (*it).first.m_lcId << ", "
-                                 << (*it).second << std::endl;
-    }
-  for ( itData = m_rxData.begin(); itData != m_rxData.end(); ++itData)
-    {
-      m_outFile << "RxData, " << (*itData).first.m_rnti << ", "
-                              << (uint32_t) (*itData).first.m_lcId << ", "
-                              << (*itData).second << std::endl;
-    }
-  for ( itData = m_rxData.begin(); itData != m_rxData.end(); ++itData)
-    {
-      m_outFile << "Throughput, " << (*itData).first.m_rnti << ", "
-                                  << (uint32_t) (*itData).first.m_lcId << ", "
-                                  << GetThroughput ((*itData).first) << std::endl;
-    }
-  for ( itDelay = m_delay.begin (); itDelay != m_delay.end (); ++itDelay)
-    {
-      m_outFile << "Delay, " << (*itDelay).first.m_rnti << ", "
-                             << (uint32_t) (*itDelay).first.m_lcId << ", "
-                             << GetDelay ((*itDelay).first) << std::endl;
+      if (find (lteFlowIds.begin (), lteFlowIds.end (),  (*it).first ) == lteFlowIds.end () )
+        {
+          lteFlowIds.push_back ((*it).first);
+        }
     }
 
+  std::vector<lteFlowId_t>::iterator itFlow;
+  Time endTime = m_startTime + m_epochDuration;
+  for ( itFlow = lteFlowIds.begin(); itFlow != lteFlowIds.end(); ++itFlow)
+    {
+      m_outFile << m_startTime.GetNanoSeconds () / 1.0e9  << " " << endTime.GetNanoSeconds() / 1.0e9;
+      m_outFile << " " << (*itFlow).m_rnti << " " << (uint32_t) (*itFlow).m_lcId << " " << GetThroughput (*itFlow);
+      m_outFile << " " << GetDelay(*itFlow) << " " << GetPacketLossProbability (*itFlow) << std::endl;
+    }
   m_outFile.close ();
 }
 
+void
+RlcStatsCalculator::ResetResults (void)
+{
+   m_txPackets.erase (m_txPackets.begin (), m_txPackets.end () );
+   m_rxPackets.erase (m_rxPackets.begin (), m_rxPackets.end () );
+   m_rxData.erase (m_rxData.begin (), m_rxData.end () );
+   m_throughput.erase (m_throughput.begin (), m_throughput.end () );
+   m_delay.erase (m_delay.begin (), m_delay.end () );
+}
+
+void
+RlcStatsCalculator::CheckEpoch (void)
+{
+  if ( Simulator::Now () > m_startTime + m_epochDuration )
+    {
+      ShowResults();
+      ResetResults();
+      StartEpoch();
+    }
+
+}
+
+void
+RlcStatsCalculator::StartEpoch (void)
+{
+  m_startTime += m_epochDuration;
+}
+
 uint32_t
 RlcStatsCalculator::GetTxPackets (lteFlowId_t p)
 {
@@ -174,10 +222,13 @@
 double
 RlcStatsCalculator::GetThroughput (lteFlowId_t p)
 {
-  // TODO: Fix throughput calculation with the correct time
-  // NOTE: At this moment, Simulator::Now() is not available anymore
-  //return (double) m_rxData[p] / Simulator::Now().GetSeconds();
-  return 0;
+  return m_throughput[p];
+}
+
+double
+RlcStatsCalculator::GetPacketLossProbability (lteFlowId_t p)
+{
+   return (GetTxPackets (p) - GetRxPackets (p)) / (double) GetTxPackets (p);
 }
 
 uint32_t
@@ -215,4 +266,11 @@
   return GetThroughput (p);
 }
 
+double
+RlcStatsCalculator::GetPacketLossProbability (uint16_t rnti, uint8_t lcid)
+{
+  lteFlowId_t p (rnti, lcid);
+  return GetPacketLossProbability (p);
+}
+
 } // namespace ns3
--- a/src/lte/helper/rlc-stats-calculator.h	Fri Apr 01 12:02:18 2011 +0200
+++ b/src/lte/helper/rlc-stats-calculator.h	Mon Apr 04 18:17:17 2011 +0200
@@ -35,6 +35,7 @@
 typedef std::map<lteFlowId_t, uint32_t> uint32Map;
 typedef std::map<lteFlowId_t, uint64_t> uint64Map;
 typedef std::map<lteFlowId_t, Ptr<MinMaxAvgTotalCalculator<uint64_t> > > uint64StatsMap;
+typedef std::map<lteFlowId_t, double> doubleMap;
 
 
 class RlcStatsCalculator : public Object
@@ -55,21 +56,42 @@
   uint64_t GetRxData (lteFlowId_t p);
   uint64_t GetDelay (lteFlowId_t p);
   double   GetThroughput (lteFlowId_t p);
+  double   GetPacketLossProbability (lteFlowId_t p);
 
   uint32_t GetTxPackets (uint16_t rnti, uint8_t lcid);
   uint32_t GetRxPackets (uint16_t rnti, uint8_t lcid);
   uint64_t GetRxData (uint16_t rnti, uint8_t lcid);
   uint64_t GetDelay (uint16_t rnti, uint8_t lcid);
   double   GetThroughput (uint16_t rnti, uint8_t lcid);
+  double   GetPacketLossProbability (uint16_t rnti, uint8_t lcid);
 
 private:
   void ShowResults (void);
+  void ResetResults (void);
+
+  void StartEpoch (void);
+  void CheckEpoch (void);
+
   std::string m_outputFilename;
   std::ofstream m_outFile;
   uint32Map m_txPackets;
   uint32Map m_rxPackets;
   uint64Map m_rxData;
+  doubleMap m_throughput;
   uint64StatsMap m_delay;
+
+  /**
+   * Start time of the on going epoch
+   */
+  Time m_startTime;
+
+  /**
+   * Epoch duration
+   */
+  Time m_epochDuration;
+
+  bool m_firstWrite;
+
 };
 
 } // namespace ns3