Merge pull request #350 from pstavirs/streamrates
Add average rate per GUID in stream statistics
This commit is contained in:
commit
5e7bf77b0c
@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include "streamstatsmodel.h"
|
||||
|
||||
#include "protocol.pb.h"
|
||||
#include "xqlocale.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QBrush>
|
||||
@ -45,12 +46,22 @@ enum {
|
||||
kAggrTxPkts,
|
||||
kAggrRxPkts,
|
||||
kAggrPktLoss,
|
||||
kTxDuration,
|
||||
kAvgTxFrameRate,
|
||||
kAvgRxFrameRate,
|
||||
kAvgTxBitRate,
|
||||
kAvgRxBitRate,
|
||||
kMaxAggrStreamStats
|
||||
};
|
||||
static QStringList aggrStatTitles = QStringList()
|
||||
<< "Total\nTx Pkts"
|
||||
<< "Total\nRx Pkts"
|
||||
<< "Total\nPkt Loss";
|
||||
<< "Total\nPkt Loss"
|
||||
<< "Duration\n(secs)"
|
||||
<< "Avg\nTx PktRate"
|
||||
<< "Avg\nRx PktRate"
|
||||
<< "Avg\nTx BitRate"
|
||||
<< "Avg\nRx BitRate";
|
||||
|
||||
static const uint kAggrGuid = 0xffffffff;
|
||||
|
||||
@ -149,6 +160,26 @@ QVariant StreamStatsModel::data(const QModelIndex &index, int role) const
|
||||
return QString("%L1").arg(aggrGuidStats_.value(guid).txPkts);
|
||||
case kAggrPktLoss:
|
||||
return QString("%L1").arg(aggrGuidStats_.value(guid).pktLoss);
|
||||
case kTxDuration:
|
||||
return QString("%L1").arg(aggrGuidStats_.value(guid).txDuration);
|
||||
case kAvgTxFrameRate:
|
||||
return QString("%L1").arg(
|
||||
aggrGuidStats_.value(guid).txPkts
|
||||
/ aggrGuidStats_.value(guid).txDuration);
|
||||
case kAvgRxFrameRate:
|
||||
return QString("%L1").arg(
|
||||
aggrGuidStats_.value(guid).rxPkts
|
||||
/ aggrGuidStats_.value(guid).txDuration);
|
||||
case kAvgTxBitRate:
|
||||
return XLocale().toBitRateString(
|
||||
(aggrGuidStats_.value(guid).txBytes
|
||||
+ 24 * aggrGuidStats_.value(guid).txPkts) * 8
|
||||
/ aggrGuidStats_.value(guid).txDuration);
|
||||
case kAvgRxBitRate:
|
||||
return XLocale().toBitRateString(
|
||||
(aggrGuidStats_.value(guid).rxBytes
|
||||
+ 24 * aggrGuidStats_.value(guid).rxPkts) * 8
|
||||
/ aggrGuidStats_.value(guid).txDuration);
|
||||
default:
|
||||
break;
|
||||
};
|
||||
@ -232,10 +263,18 @@ void StreamStatsModel::appendStreamStatsList(
|
||||
aggrGuid.rxPkts += ss.rxPkts;
|
||||
aggrGuid.txPkts += ss.txPkts;
|
||||
aggrGuid.pktLoss += ss.txPkts - ss.rxPkts;
|
||||
aggrGuid.rxBytes += ss.rxBytes;
|
||||
aggrGuid.txBytes += ss.txBytes;
|
||||
if (s.tx_duration() > aggrGuid.txDuration)
|
||||
aggrGuid.txDuration = s.tx_duration(); // XXX: use largest or avg?
|
||||
|
||||
aggrAggr.rxPkts += ss.rxPkts;
|
||||
aggrAggr.txPkts += ss.txPkts;
|
||||
aggrAggr.pktLoss += ss.txPkts - ss.rxPkts;
|
||||
aggrAggr.rxBytes += ss.rxBytes;
|
||||
aggrAggr.txBytes += ss.txBytes;
|
||||
if (aggrGuid.txDuration > aggrAggr.txDuration)
|
||||
aggrAggr.txDuration = aggrGuid.txDuration;
|
||||
|
||||
if (!portList_.contains(pgp))
|
||||
portList_.append(pgp);
|
||||
@ -246,6 +285,8 @@ void StreamStatsModel::appendStreamStatsList(
|
||||
if (guidList_.size() && !guidList_.contains(kAggrGuid))
|
||||
guidList_.append(kAggrGuid);
|
||||
|
||||
std::sort(guidList_.begin(), guidList_.end());
|
||||
|
||||
#if QT_VERSION >= 0x040600
|
||||
endResetModel();
|
||||
#else
|
||||
|
@ -61,7 +61,10 @@ private:
|
||||
struct AggrGuidStats {
|
||||
quint64 rxPkts;
|
||||
quint64 txPkts;
|
||||
quint64 rxBytes;
|
||||
quint64 txBytes;
|
||||
qint64 pktLoss;
|
||||
double txDuration;
|
||||
};
|
||||
QList<Guid> guidList_;
|
||||
QList<PortGroupPort> portList_;
|
||||
|
@ -31,7 +31,7 @@ StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
streamStats->addAction(actionShowByteCounters);
|
||||
streamStats->addAction(actionShowDetails);
|
||||
|
||||
if (id)
|
||||
setWindowTitle(windowTitle() + QString("(%1)").arg(id));
|
||||
@ -39,7 +39,7 @@ StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent)
|
||||
count++;
|
||||
|
||||
filterModel_ = new StreamStatsFilterModel(this);
|
||||
filterModel_->setFilterRegExp(QRegExp(".*Pkt.*"));
|
||||
filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
|
||||
filterModel_->setSourceModel(model);
|
||||
streamStats->setModel(filterModel_);
|
||||
|
||||
@ -56,10 +56,10 @@ StreamStatsWindow::~StreamStatsWindow()
|
||||
id = 0;
|
||||
}
|
||||
|
||||
void StreamStatsWindow::on_actionShowByteCounters_triggered(bool checked)
|
||||
void StreamStatsWindow::on_actionShowDetails_triggered(bool checked)
|
||||
{
|
||||
if (checked)
|
||||
filterModel_->setFilterRegExp(QRegExp(".*"));
|
||||
else
|
||||
filterModel_->setFilterRegExp(QRegExp(".*Pkt.*"));
|
||||
filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
|
||||
}
|
||||
|
@ -33,9 +33,10 @@ public:
|
||||
~StreamStatsWindow();
|
||||
|
||||
private slots:
|
||||
void on_actionShowByteCounters_triggered(bool checked);
|
||||
void on_actionShowDetails_triggered(bool checked);
|
||||
|
||||
private:
|
||||
QString kDefaultFilter_{"^(?!Port).*"};
|
||||
QSortFilterProxyModel *filterModel_;
|
||||
};
|
||||
|
||||
|
@ -27,12 +27,12 @@ Wait a little bit to see if they appear, otherwise verify your stream stats conf
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionShowByteCounters">
|
||||
<action name="actionShowDetails">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Byte Counters</string>
|
||||
<string>Show Details</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
|
@ -290,6 +290,8 @@ message StreamStats {
|
||||
required PortId port_id = 1;
|
||||
required StreamGuid stream_guid = 2;
|
||||
|
||||
optional double tx_duration = 3; // in seconds
|
||||
|
||||
optional uint64 rx_pkts = 11;
|
||||
optional uint64 rx_bytes = 12;
|
||||
optional uint64 tx_pkts = 13;
|
||||
|
@ -714,6 +714,8 @@ void AbstractPort::streamStats(uint guid, OstProto::StreamStatsList *stats)
|
||||
s->mutable_stream_guid()->set_id(guid);
|
||||
s->mutable_port_id()->set_id(id());
|
||||
|
||||
s->set_tx_duration(lastTransmitDuration());
|
||||
|
||||
s->set_tx_pkts(sst.tx_pkts);
|
||||
s->set_tx_bytes(sst.tx_bytes);
|
||||
s->set_rx_pkts(sst.rx_pkts);
|
||||
@ -725,6 +727,7 @@ void AbstractPort::streamStatsAll(OstProto::StreamStatsList *stats)
|
||||
{
|
||||
// FIXME: change input param to a non-OstProto type and/or have
|
||||
// a getFirst/Next like API?
|
||||
double txDur = lastTransmitDuration();
|
||||
StreamStatsIterator i(streamStats_);
|
||||
while (i.hasNext())
|
||||
{
|
||||
@ -735,6 +738,8 @@ void AbstractPort::streamStatsAll(OstProto::StreamStatsList *stats)
|
||||
s->mutable_stream_guid()->set_id(i.key());
|
||||
s->mutable_port_id()->set_id(id());
|
||||
|
||||
s->set_tx_duration(txDur);
|
||||
|
||||
s->set_tx_pkts(sst.tx_pkts);
|
||||
s->set_tx_bytes(sst.tx_bytes);
|
||||
s->set_rx_pkts(sst.rx_pkts);
|
||||
|
@ -110,6 +110,7 @@ public:
|
||||
virtual void startTransmit() = 0;
|
||||
virtual void stopTransmit() = 0;
|
||||
virtual bool isTransmitOn() = 0;
|
||||
virtual double lastTransmitDuration() = 0;
|
||||
|
||||
virtual void startCapture() = 0;
|
||||
virtual void stopCapture() = 0;
|
||||
|
@ -68,6 +68,9 @@ public:
|
||||
}
|
||||
virtual void stopTransmit() { transmitter_->stop(); }
|
||||
virtual bool isTransmitOn() { return transmitter_->isRunning(); }
|
||||
virtual double lastTransmitDuration() {
|
||||
return transmitter_->lastTxDuration();
|
||||
}
|
||||
|
||||
virtual void startCapture() { capturer_->start(); }
|
||||
virtual void stopCapture() { capturer_->stop(); }
|
||||
|
@ -107,6 +107,10 @@ bool PcapTransmitter::isRunning()
|
||||
{
|
||||
return txThread_.isRunning();
|
||||
}
|
||||
double PcapTransmitter::lastTxDuration()
|
||||
{
|
||||
return txThread_.lastTxDuration();
|
||||
}
|
||||
|
||||
void PcapTransmitter::updateTxThreadStreamStats()
|
||||
{
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
void start();
|
||||
void stop();
|
||||
bool isRunning();
|
||||
double lastTxDuration();
|
||||
private slots:
|
||||
void updateTxThreadStreamStats();
|
||||
private:
|
||||
|
@ -243,6 +243,7 @@ void PcapTxThread::run()
|
||||
const int kSyncTransmit = 1;
|
||||
int i;
|
||||
long overHead = 0; // overHead should be negative or zero
|
||||
TimeStamp startTime, endTime;
|
||||
|
||||
qDebug("packetSequenceList_.size = %d", packetSequenceList_.size());
|
||||
if (packetSequenceList_.size() <= 0)
|
||||
@ -260,6 +261,7 @@ void PcapTxThread::run()
|
||||
|
||||
lastStats_ = *stats_; // used for stream stats
|
||||
|
||||
getTimeStamp(&startTime);
|
||||
state_ = kRunning;
|
||||
i = 0;
|
||||
while (i < packetSequenceList_.size())
|
||||
@ -348,6 +350,10 @@ _restart:
|
||||
}
|
||||
|
||||
_exit:
|
||||
getTimeStamp(&endTime);
|
||||
lastTxDuration_ = udiffTimeStamp(&startTime, &endTime)/1e6;
|
||||
qDebug("Tx duration = %fs", lastTxDuration_);
|
||||
|
||||
if (trackStreamStats_)
|
||||
updateStreamStats();
|
||||
|
||||
@ -388,6 +394,11 @@ bool PcapTxThread::isRunning()
|
||||
return (state_ == kRunning);
|
||||
}
|
||||
|
||||
double PcapTxThread::lastTxDuration()
|
||||
{
|
||||
return lastTxDuration_;
|
||||
}
|
||||
|
||||
int PcapTxThread::sendQueueTransmit(pcap_t *p,
|
||||
pcap_send_queue *queue, long &overHead, int sync)
|
||||
{
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
void start();
|
||||
void stop();
|
||||
bool isRunning();
|
||||
double lastTxDuration();
|
||||
|
||||
private:
|
||||
enum State
|
||||
@ -92,6 +93,8 @@ private:
|
||||
StatsTuple *stats_;
|
||||
StatsTuple lastStats_;
|
||||
StreamStats streamStats_;
|
||||
|
||||
double lastTxDuration_{0.0}; // in secs
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user