Merge pull request #350 from pstavirs/streamrates

Add average rate per GUID in stream statistics
This commit is contained in:
Srivats P 2022-06-20 17:27:24 +05:30 committed by GitHub
commit 5e7bf77b0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 83 additions and 8 deletions

View File

@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "streamstatsmodel.h" #include "streamstatsmodel.h"
#include "protocol.pb.h" #include "protocol.pb.h"
#include "xqlocale.h"
#include <QApplication> #include <QApplication>
#include <QBrush> #include <QBrush>
@ -45,12 +46,22 @@ enum {
kAggrTxPkts, kAggrTxPkts,
kAggrRxPkts, kAggrRxPkts,
kAggrPktLoss, kAggrPktLoss,
kTxDuration,
kAvgTxFrameRate,
kAvgRxFrameRate,
kAvgTxBitRate,
kAvgRxBitRate,
kMaxAggrStreamStats kMaxAggrStreamStats
}; };
static QStringList aggrStatTitles = QStringList() static QStringList aggrStatTitles = QStringList()
<< "Total\nTx Pkts" << "Total\nTx Pkts"
<< "Total\nRx 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; 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); return QString("%L1").arg(aggrGuidStats_.value(guid).txPkts);
case kAggrPktLoss: case kAggrPktLoss:
return QString("%L1").arg(aggrGuidStats_.value(guid).pktLoss); 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: default:
break; break;
}; };
@ -232,10 +263,18 @@ void StreamStatsModel::appendStreamStatsList(
aggrGuid.rxPkts += ss.rxPkts; aggrGuid.rxPkts += ss.rxPkts;
aggrGuid.txPkts += ss.txPkts; aggrGuid.txPkts += ss.txPkts;
aggrGuid.pktLoss += ss.txPkts - ss.rxPkts; 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.rxPkts += ss.rxPkts;
aggrAggr.txPkts += ss.txPkts; aggrAggr.txPkts += ss.txPkts;
aggrAggr.pktLoss += ss.txPkts - ss.rxPkts; 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)) if (!portList_.contains(pgp))
portList_.append(pgp); portList_.append(pgp);
@ -246,6 +285,8 @@ void StreamStatsModel::appendStreamStatsList(
if (guidList_.size() && !guidList_.contains(kAggrGuid)) if (guidList_.size() && !guidList_.contains(kAggrGuid))
guidList_.append(kAggrGuid); guidList_.append(kAggrGuid);
std::sort(guidList_.begin(), guidList_.end());
#if QT_VERSION >= 0x040600 #if QT_VERSION >= 0x040600
endResetModel(); endResetModel();
#else #else

View File

@ -61,7 +61,10 @@ private:
struct AggrGuidStats { struct AggrGuidStats {
quint64 rxPkts; quint64 rxPkts;
quint64 txPkts; quint64 txPkts;
quint64 rxBytes;
quint64 txBytes;
qint64 pktLoss; qint64 pktLoss;
double txDuration;
}; };
QList<Guid> guidList_; QList<Guid> guidList_;
QList<PortGroupPort> portList_; QList<PortGroupPort> portList_;

View File

@ -31,7 +31,7 @@ StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent)
: QWidget(parent) : QWidget(parent)
{ {
setupUi(this); setupUi(this);
streamStats->addAction(actionShowByteCounters); streamStats->addAction(actionShowDetails);
if (id) if (id)
setWindowTitle(windowTitle() + QString("(%1)").arg(id)); setWindowTitle(windowTitle() + QString("(%1)").arg(id));
@ -39,7 +39,7 @@ StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent)
count++; count++;
filterModel_ = new StreamStatsFilterModel(this); filterModel_ = new StreamStatsFilterModel(this);
filterModel_->setFilterRegExp(QRegExp(".*Pkt.*")); filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
filterModel_->setSourceModel(model); filterModel_->setSourceModel(model);
streamStats->setModel(filterModel_); streamStats->setModel(filterModel_);
@ -56,10 +56,10 @@ StreamStatsWindow::~StreamStatsWindow()
id = 0; id = 0;
} }
void StreamStatsWindow::on_actionShowByteCounters_triggered(bool checked) void StreamStatsWindow::on_actionShowDetails_triggered(bool checked)
{ {
if (checked) if (checked)
filterModel_->setFilterRegExp(QRegExp(".*")); filterModel_->setFilterRegExp(QRegExp(".*"));
else else
filterModel_->setFilterRegExp(QRegExp(".*Pkt.*")); filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
} }

View File

@ -33,9 +33,10 @@ public:
~StreamStatsWindow(); ~StreamStatsWindow();
private slots: private slots:
void on_actionShowByteCounters_triggered(bool checked); void on_actionShowDetails_triggered(bool checked);
private: private:
QString kDefaultFilter_{"^(?!Port).*"};
QSortFilterProxyModel *filterModel_; QSortFilterProxyModel *filterModel_;
}; };

View File

@ -27,12 +27,12 @@ Wait a little bit to see if they appear, otherwise verify your stream stats conf
</widget> </widget>
</item> </item>
</layout> </layout>
<action name="actionShowByteCounters"> <action name="actionShowDetails">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Show Byte Counters</string> <string>Show Details</string>
</property> </property>
</action> </action>
</widget> </widget>

View File

@ -290,6 +290,8 @@ message StreamStats {
required PortId port_id = 1; required PortId port_id = 1;
required StreamGuid stream_guid = 2; required StreamGuid stream_guid = 2;
optional double tx_duration = 3; // in seconds
optional uint64 rx_pkts = 11; optional uint64 rx_pkts = 11;
optional uint64 rx_bytes = 12; optional uint64 rx_bytes = 12;
optional uint64 tx_pkts = 13; optional uint64 tx_pkts = 13;

View File

@ -714,6 +714,8 @@ void AbstractPort::streamStats(uint guid, OstProto::StreamStatsList *stats)
s->mutable_stream_guid()->set_id(guid); s->mutable_stream_guid()->set_id(guid);
s->mutable_port_id()->set_id(id()); s->mutable_port_id()->set_id(id());
s->set_tx_duration(lastTransmitDuration());
s->set_tx_pkts(sst.tx_pkts); s->set_tx_pkts(sst.tx_pkts);
s->set_tx_bytes(sst.tx_bytes); s->set_tx_bytes(sst.tx_bytes);
s->set_rx_pkts(sst.rx_pkts); 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 // FIXME: change input param to a non-OstProto type and/or have
// a getFirst/Next like API? // a getFirst/Next like API?
double txDur = lastTransmitDuration();
StreamStatsIterator i(streamStats_); StreamStatsIterator i(streamStats_);
while (i.hasNext()) while (i.hasNext())
{ {
@ -735,6 +738,8 @@ void AbstractPort::streamStatsAll(OstProto::StreamStatsList *stats)
s->mutable_stream_guid()->set_id(i.key()); s->mutable_stream_guid()->set_id(i.key());
s->mutable_port_id()->set_id(id()); s->mutable_port_id()->set_id(id());
s->set_tx_duration(txDur);
s->set_tx_pkts(sst.tx_pkts); s->set_tx_pkts(sst.tx_pkts);
s->set_tx_bytes(sst.tx_bytes); s->set_tx_bytes(sst.tx_bytes);
s->set_rx_pkts(sst.rx_pkts); s->set_rx_pkts(sst.rx_pkts);

View File

@ -110,6 +110,7 @@ public:
virtual void startTransmit() = 0; virtual void startTransmit() = 0;
virtual void stopTransmit() = 0; virtual void stopTransmit() = 0;
virtual bool isTransmitOn() = 0; virtual bool isTransmitOn() = 0;
virtual double lastTransmitDuration() = 0;
virtual void startCapture() = 0; virtual void startCapture() = 0;
virtual void stopCapture() = 0; virtual void stopCapture() = 0;

View File

@ -68,6 +68,9 @@ public:
} }
virtual void stopTransmit() { transmitter_->stop(); } virtual void stopTransmit() { transmitter_->stop(); }
virtual bool isTransmitOn() { return transmitter_->isRunning(); } virtual bool isTransmitOn() { return transmitter_->isRunning(); }
virtual double lastTransmitDuration() {
return transmitter_->lastTxDuration();
}
virtual void startCapture() { capturer_->start(); } virtual void startCapture() { capturer_->start(); }
virtual void stopCapture() { capturer_->stop(); } virtual void stopCapture() { capturer_->stop(); }

View File

@ -107,6 +107,10 @@ bool PcapTransmitter::isRunning()
{ {
return txThread_.isRunning(); return txThread_.isRunning();
} }
double PcapTransmitter::lastTxDuration()
{
return txThread_.lastTxDuration();
}
void PcapTransmitter::updateTxThreadStreamStats() void PcapTransmitter::updateTxThreadStreamStats()
{ {

View File

@ -49,6 +49,7 @@ public:
void start(); void start();
void stop(); void stop();
bool isRunning(); bool isRunning();
double lastTxDuration();
private slots: private slots:
void updateTxThreadStreamStats(); void updateTxThreadStreamStats();
private: private:

View File

@ -243,6 +243,7 @@ void PcapTxThread::run()
const int kSyncTransmit = 1; const int kSyncTransmit = 1;
int i; int i;
long overHead = 0; // overHead should be negative or zero long overHead = 0; // overHead should be negative or zero
TimeStamp startTime, endTime;
qDebug("packetSequenceList_.size = %d", packetSequenceList_.size()); qDebug("packetSequenceList_.size = %d", packetSequenceList_.size());
if (packetSequenceList_.size() <= 0) if (packetSequenceList_.size() <= 0)
@ -260,6 +261,7 @@ void PcapTxThread::run()
lastStats_ = *stats_; // used for stream stats lastStats_ = *stats_; // used for stream stats
getTimeStamp(&startTime);
state_ = kRunning; state_ = kRunning;
i = 0; i = 0;
while (i < packetSequenceList_.size()) while (i < packetSequenceList_.size())
@ -348,6 +350,10 @@ _restart:
} }
_exit: _exit:
getTimeStamp(&endTime);
lastTxDuration_ = udiffTimeStamp(&startTime, &endTime)/1e6;
qDebug("Tx duration = %fs", lastTxDuration_);
if (trackStreamStats_) if (trackStreamStats_)
updateStreamStats(); updateStreamStats();
@ -388,6 +394,11 @@ bool PcapTxThread::isRunning()
return (state_ == kRunning); return (state_ == kRunning);
} }
double PcapTxThread::lastTxDuration()
{
return lastTxDuration_;
}
int PcapTxThread::sendQueueTransmit(pcap_t *p, int PcapTxThread::sendQueueTransmit(pcap_t *p,
pcap_send_queue *queue, long &overHead, int sync) pcap_send_queue *queue, long &overHead, int sync)
{ {

View File

@ -55,6 +55,7 @@ public:
void start(); void start();
void stop(); void stop();
bool isRunning(); bool isRunning();
double lastTxDuration();
private: private:
enum State enum State
@ -92,6 +93,8 @@ private:
StatsTuple *stats_; StatsTuple *stats_;
StatsTuple lastStats_; StatsTuple lastStats_;
StreamStats streamStats_; StreamStats streamStats_;
double lastTxDuration_{0.0}; // in secs
}; };
#endif #endif