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 "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

View File

@ -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_;

View File

@ -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_));
}

View File

@ -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_;
};

View File

@ -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>

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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(); }

View File

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

View File

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

View File

@ -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)
{

View File

@ -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