Fixed throughput calculation
Fixed output format to be compliant with Requirements Document
This commit is contained in:
@@ -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_LOG_COMPONENT_DEFINE ("RlcStatsCalculator");
|
||||
NS_OBJECT_ENSURE_REGISTERED (RlcStatsCalculator);
|
||||
|
||||
RlcStatsCalculator::RlcStatsCalculator() :
|
||||
m_outputFilename ("")
|
||||
m_outputFilename (""),
|
||||
m_firstWrite(true)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
@@ -53,6 +56,15 @@ RlcStatsCalculator::GetTypeId (void)
|
||||
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 @@ void
|
||||
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;
|
||||
|
||||
uint64StatsMap::iterator it = m_delay.find (pair);
|
||||
if ( it == m_delay.end () )
|
||||
if (Simulator::Now () > m_startTime )
|
||||
{
|
||||
m_delay[pair] = CreateObject <MinMaxAvgTotalCalculator<uint64_t> > ();
|
||||
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> > ();
|
||||
}
|
||||
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 @@ RlcStatsCalculator::GetDelay (lteFlowId_t p)
|
||||
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 @@ RlcStatsCalculator::GetThroughput (uint16_t rnti, uint8_t lcid)
|
||||
return GetThroughput (p);
|
||||
}
|
||||
|
||||
double
|
||||
RlcStatsCalculator::GetPacketLossProbability (uint16_t rnti, uint8_t lcid)
|
||||
{
|
||||
lteFlowId_t p (rnti, lcid);
|
||||
return GetPacketLossProbability (p);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace ns3 {
|
||||
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 @@ public:
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user