Compare commits
50 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ca956c3c18 | ||
|
f98c8af594 | ||
|
accc47fa34 | ||
|
6f71844f7c | ||
|
bd2a4715dc | ||
|
4886739da6 | ||
|
80a4578847 | ||
|
390ffae2b4 | ||
|
d17ab7ab42 | ||
|
5abd6fb962 | ||
|
3c0bc067fa | ||
|
223e44a6e3 | ||
|
6108de9b4f | ||
|
e761bfa5c4 | ||
|
b9345463c4 | ||
|
dc6c4963a2 | ||
|
cded62246e | ||
|
10befe0a66 | ||
|
4394c7ffee | ||
|
ef1c166e7f | ||
|
d1d2a5c1b5 | ||
|
f56ce2e2ec | ||
|
c91475d416 | ||
|
b2ad3c5d08 | ||
|
896371b987 | ||
|
f5bb2e5d80 | ||
|
7cfccd686e | ||
|
2e502434db | ||
|
aa140cd32a | ||
|
3b499263ec | ||
|
c378600baf | ||
|
68734c44ca | ||
|
05a9dd5743 | ||
|
05335b31d5 | ||
|
f4c21e1ae4 | ||
|
757d3f1b24 | ||
|
7e30ef5541 | ||
|
f7b6b46a5d | ||
|
823f01557b | ||
|
682d0cc5c9 | ||
|
f1cfaa6e89 | ||
|
072dfcdc3b | ||
|
90a3731a90 | ||
|
5d4a19174e | ||
|
2104936b69 | ||
|
5dc1b851cc | ||
|
8e25669a0e | ||
|
ebccc44cdf | ||
|
f3a9b507b0 | ||
|
620004d46b |
@ -13,11 +13,11 @@ I have been developing and maintaining Ostinato [single-handedly](https://github
|
|||||||
|
|
||||||
I sell binary licenses on [ostinato.org](https://ostinato.org/downloads) to try and cover the costs of development. Please consider buying those - they are priced low enough that you can afford it or you could just as easily expense them to your organisation.
|
I sell binary licenses on [ostinato.org](https://ostinato.org/downloads) to try and cover the costs of development. Please consider buying those - they are priced low enough that you can afford it or you could just as easily expense them to your organisation.
|
||||||
|
|
||||||
If you build Ostinato from source and find it useful, please sponsor to keep the lights on and sustain the project.
|
If you build Ostinato from source and find it useful, please donate to keep the lights on and sustain the project.
|
||||||
|
|
||||||
[](https://github.com/sponsors/pstavirs)
|
|
||||||
|
|
||||||
Read the Ostinato [origin story](https://ostinato.org/about).
|
Read the Ostinato [origin story](https://ostinato.org/about).
|
||||||
|
|
||||||
|
[](https://gum.co/ostdonate)
|
||||||
|
|
||||||
Srivats P<br/>
|
Srivats P<br/>
|
||||||
Author, Ostinato
|
Author, Ostinato
|
||||||
|
@ -94,7 +94,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="CopyrightLabel" >
|
<widget class="QLabel" name="CopyrightLabel" >
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>Copyright (c) 2007-2023 Srivats P.</string>
|
<string>Copyright (c) 2007-2020 Srivats P.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment" >
|
<property name="alignment" >
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignCenter</set>
|
||||||
|
@ -31,13 +31,9 @@ class IconOnlyDelegate : public QStyledItemDelegate
|
|||||||
{
|
{
|
||||||
QStyleOptionViewItem opt = option;
|
QStyleOptionViewItem opt = option;
|
||||||
opt.decorationPosition = QStyleOptionViewItem::Top;
|
opt.decorationPosition = QStyleOptionViewItem::Top;
|
||||||
|
opt.features &= ~QStyleOptionViewItem::HasDisplay;
|
||||||
QStyledItemDelegate::paint(painter, opt, index);
|
QStyledItemDelegate::paint(painter, opt, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString displayText(const QVariant&, const QLocale&) const
|
|
||||||
{
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,7 +24,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "clipboardhelper.h"
|
#include "clipboardhelper.h"
|
||||||
#include "fileformatoptions.h"
|
|
||||||
#include "jumpurl.h"
|
#include "jumpurl.h"
|
||||||
#include "logsmodel.h"
|
#include "logsmodel.h"
|
||||||
#include "logswindow.h"
|
#include "logswindow.h"
|
||||||
@ -548,7 +547,7 @@ bool MainWindow::openSession(QString fileName, QString &error)
|
|||||||
goto _fail;
|
goto _fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((optDialog = FileFormatOptions::openOptionsDialog(fmt)))
|
if ((optDialog = fmt->openOptionsDialog()))
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
optDialog->setParent(this, Qt::Dialog);
|
optDialog->setParent(this, Qt::Dialog);
|
||||||
|
@ -5,26 +5,31 @@ win32:RC_FILE = ostinato.rc
|
|||||||
macx:ICON = icons/logo.icns
|
macx:ICON = icons/logo.icns
|
||||||
QT += widgets network script xml svg
|
QT += widgets network script xml svg
|
||||||
INCLUDEPATH += "../rpc/" "../common/"
|
INCLUDEPATH += "../rpc/" "../common/"
|
||||||
|
|
||||||
OBJDIR = .
|
|
||||||
win32 {
|
win32 {
|
||||||
QMAKE_LFLAGS += -static
|
QMAKE_LFLAGS += -static
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
OBJDIR = debug
|
LIBS += -L"../common/debug" -lostprotogui -lostproto
|
||||||
|
LIBS += -L"../rpc/debug" -lpbrpc
|
||||||
|
POST_TARGETDEPS += \
|
||||||
|
"../common/debug/libostprotogui.a" \
|
||||||
|
"../common/debug/libostproto.a" \
|
||||||
|
"../rpc/debug/libpbrpc.a"
|
||||||
} else {
|
} else {
|
||||||
OBJDIR = release
|
LIBS += -L"../common/release" -lostprotogui -lostproto
|
||||||
|
LIBS += -L"../rpc/release" -lpbrpc
|
||||||
|
POST_TARGETDEPS += \
|
||||||
|
"../common/release/libostprotogui.a" \
|
||||||
|
"../common/release/libostproto.a" \
|
||||||
|
"../rpc/release/libpbrpc.a"
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LIBS += -L"../common" -lostprotogui -lostproto
|
||||||
|
LIBS += -L"../rpc" -lpbrpc
|
||||||
|
POST_TARGETDEPS += \
|
||||||
|
"../common/libostprotogui.a" \
|
||||||
|
"../common/libostproto.a" \
|
||||||
|
"../rpc/libpbrpc.a"
|
||||||
}
|
}
|
||||||
LIBS += -L"../common/$$OBJDIR" -lostfile -lostfilegui
|
|
||||||
LIBS += -L"../common/$$OBJDIR" -lostprotogui -lostproto
|
|
||||||
LIBS += -L"../rpc/$$OBJDIR" -lpbrpc
|
|
||||||
POST_TARGETDEPS += \
|
|
||||||
"../common/$$OBJDIR/libostfilegui.a" \
|
|
||||||
"../common/$$OBJDIR/libostfile.a" \
|
|
||||||
"../common/$$OBJDIR/libostprotogui.a" \
|
|
||||||
"../common/$$OBJDIR/libostproto.a" \
|
|
||||||
"../rpc/$$OBJDIR/libpbrpc.a"
|
|
||||||
|
|
||||||
LIBS += -lprotobuf
|
LIBS += -lprotobuf
|
||||||
LIBS += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
|
LIBS += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
|
||||||
RESOURCES += ostinato.qrc
|
RESOURCES += ostinato.qrc
|
||||||
|
@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
|
||||||
#include "emulation.h"
|
#include "emulation.h"
|
||||||
#include "fileformatoptions.h"
|
|
||||||
#include "streamfileformat.h"
|
#include "streamfileformat.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -605,7 +604,7 @@ bool Port::openStreams(QString fileName, bool append, QString &error)
|
|||||||
goto _fail;
|
goto _fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((optDialog = FileFormatOptions::openOptionsDialog(fmt)))
|
if ((optDialog = fmt->openOptionsDialog()))
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
optDialog->setParent(mainWindow, Qt::Dialog);
|
optDialog->setParent(mainWindow, Qt::Dialog);
|
||||||
|
@ -137,10 +137,7 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
// States
|
// States
|
||||||
case e_COMBO_STATE:
|
case e_COMBO_STATE:
|
||||||
return QString("Link %1%2%3")
|
return QVariant();
|
||||||
.arg(LinkStateName.at(stats.state().link_state()))
|
|
||||||
.arg(stats.state().is_transmit_on() ? ";Tx On" : "")
|
|
||||||
.arg(stats.state().is_capture_on() ? ";Cap On" : "");
|
|
||||||
|
|
||||||
// Statistics
|
// Statistics
|
||||||
case e_STAT_FRAMES_RCVD:
|
case e_STAT_FRAMES_RCVD:
|
||||||
|
@ -22,12 +22,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
class PortStatsProxyModel : public QSortFilterProxyModel
|
class PortStatsProxyModel : public QSortFilterProxyModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
PortStatsProxyModel(int userRow, QObject *parent = 0)
|
PortStatsProxyModel(QSet<int> hiddenRows = QSet<int>(),
|
||||||
: QSortFilterProxyModel(parent), userRow_(userRow)
|
QObject *parent = 0)
|
||||||
|
: QSortFilterProxyModel(parent), hiddenRows_(hiddenRows)
|
||||||
{
|
{
|
||||||
setFilterRegExp(QRegExp(".*"));
|
setFilterRegExp(QRegExp(".*"));
|
||||||
}
|
}
|
||||||
@ -36,7 +39,7 @@ protected:
|
|||||||
bool filterAcceptsColumn(int sourceColumn,
|
bool filterAcceptsColumn(int sourceColumn,
|
||||||
const QModelIndex &sourceParent) const
|
const QModelIndex &sourceParent) const
|
||||||
{
|
{
|
||||||
QModelIndex index = sourceModel()->index(userRow_, sourceColumn,sourceParent);
|
QModelIndex index = sourceModel()->index(0, sourceColumn, sourceParent);
|
||||||
QString user = sourceModel()->data(index).toString();
|
QString user = sourceModel()->data(index).toString();
|
||||||
|
|
||||||
return filterRegExp().exactMatch(user) ? true : false;
|
return filterRegExp().exactMatch(user) ? true : false;
|
||||||
@ -44,10 +47,10 @@ protected:
|
|||||||
bool filterAcceptsRow(int sourceRow,
|
bool filterAcceptsRow(int sourceRow,
|
||||||
const QModelIndex &/*sourceParent*/) const
|
const QModelIndex &/*sourceParent*/) const
|
||||||
{
|
{
|
||||||
return sourceRow == userRow_ ? false : true;
|
return hiddenRows_.contains(sourceRow) ? false : true;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
int userRow_;
|
QSet<int> hiddenRows_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,7 +44,8 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
|
|||||||
model = pgl->getPortStatsModel();
|
model = pgl->getPortStatsModel();
|
||||||
|
|
||||||
// Hide 'user' row
|
// Hide 'user' row
|
||||||
proxyStatsModel = new PortStatsProxyModel(e_INFO_USER, this);
|
proxyStatsModel = new PortStatsProxyModel(
|
||||||
|
QSet<int>({e_INFO_USER}), this);
|
||||||
if (proxyStatsModel) {
|
if (proxyStatsModel) {
|
||||||
proxyStatsModel->setSourceModel(model);
|
proxyStatsModel->setSourceModel(model);
|
||||||
tvPortStats->setModel(proxyStatsModel);
|
tvPortStats->setModel(proxyStatsModel);
|
||||||
|
@ -52,7 +52,6 @@ enum {
|
|||||||
kAvgTxBitRate,
|
kAvgTxBitRate,
|
||||||
kAvgRxBitRate,
|
kAvgRxBitRate,
|
||||||
kAvgLatency,
|
kAvgLatency,
|
||||||
kAvgJitter,
|
|
||||||
kMaxAggrStreamStats
|
kMaxAggrStreamStats
|
||||||
};
|
};
|
||||||
static QStringList aggrStatTitles = QStringList()
|
static QStringList aggrStatTitles = QStringList()
|
||||||
@ -64,8 +63,7 @@ static QStringList aggrStatTitles = QStringList()
|
|||||||
<< "Avg\nRx PktRate"
|
<< "Avg\nRx PktRate"
|
||||||
<< "Avg\nTx BitRate"
|
<< "Avg\nTx BitRate"
|
||||||
<< "Avg\nRx BitRate"
|
<< "Avg\nRx BitRate"
|
||||||
<< "Avg\nLatency"
|
<< "Avg\nLatency";
|
||||||
<< "Avg\nJitter";
|
|
||||||
|
|
||||||
static const uint kAggrGuid = 0xffffffff;
|
static const uint kAggrGuid = 0xffffffff;
|
||||||
|
|
||||||
@ -168,12 +166,12 @@ QVariant StreamStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
return QString("%L1").arg(aggrGuidStats_.value(guid).txDuration);
|
return QString("%L1").arg(aggrGuidStats_.value(guid).txDuration);
|
||||||
case kAvgTxFrameRate:
|
case kAvgTxFrameRate:
|
||||||
return aggrGuidStats_.value(guid).txDuration <= 0 ? QString("-") :
|
return aggrGuidStats_.value(guid).txDuration <= 0 ? QString("-") :
|
||||||
XLocale().toPktRateString(
|
QString("%L1").arg(
|
||||||
aggrGuidStats_.value(guid).txPkts
|
aggrGuidStats_.value(guid).txPkts
|
||||||
/ aggrGuidStats_.value(guid).txDuration);
|
/ aggrGuidStats_.value(guid).txDuration);
|
||||||
case kAvgRxFrameRate:
|
case kAvgRxFrameRate:
|
||||||
return aggrGuidStats_.value(guid).txDuration <= 0 ? QString("-") :
|
return aggrGuidStats_.value(guid).txDuration <= 0 ? QString("-") :
|
||||||
XLocale().toPktRateString(
|
QString("%L1").arg(
|
||||||
aggrGuidStats_.value(guid).rxPkts
|
aggrGuidStats_.value(guid).rxPkts
|
||||||
/ aggrGuidStats_.value(guid).txDuration);
|
/ aggrGuidStats_.value(guid).txDuration);
|
||||||
case kAvgTxBitRate:
|
case kAvgTxBitRate:
|
||||||
@ -194,12 +192,6 @@ QVariant StreamStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
XLocale().toTimeIntervalString(
|
XLocale().toTimeIntervalString(
|
||||||
aggrGuidStats_.value(guid).latencySum
|
aggrGuidStats_.value(guid).latencySum
|
||||||
/ aggrGuidStats_.value(guid).latencyCount);
|
/ aggrGuidStats_.value(guid).latencyCount);
|
||||||
case kAvgJitter:
|
|
||||||
return aggrGuidStats_.value(guid).latencyCount <= 0
|
|
||||||
|| aggrGuidStats_.value(guid).latencySum <= 0 ? QString("-") :
|
|
||||||
XLocale().toTimeIntervalString(
|
|
||||||
aggrGuidStats_.value(guid).jitterSum
|
|
||||||
/ aggrGuidStats_.value(guid).latencyCount);
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
@ -275,7 +267,6 @@ void StreamStatsModel::appendStreamStatsList(
|
|||||||
ss.rxBytes = s.rx_bytes();
|
ss.rxBytes = s.rx_bytes();
|
||||||
ss.txBytes = s.tx_bytes();
|
ss.txBytes = s.tx_bytes();
|
||||||
ss.rxLatency = s.latency();
|
ss.rxLatency = s.latency();
|
||||||
ss.rxJitter = s.jitter();
|
|
||||||
|
|
||||||
aggrPort.rxPkts += ss.rxPkts;
|
aggrPort.rxPkts += ss.rxPkts;
|
||||||
aggrPort.txPkts += ss.txPkts;
|
aggrPort.txPkts += ss.txPkts;
|
||||||
@ -291,7 +282,6 @@ void StreamStatsModel::appendStreamStatsList(
|
|||||||
aggrGuid.txDuration = s.tx_duration(); // XXX: use largest or avg?
|
aggrGuid.txDuration = s.tx_duration(); // XXX: use largest or avg?
|
||||||
if (ss.rxLatency) {
|
if (ss.rxLatency) {
|
||||||
aggrGuid.latencySum += ss.rxLatency;
|
aggrGuid.latencySum += ss.rxLatency;
|
||||||
aggrGuid.jitterSum += ss.rxJitter;
|
|
||||||
aggrGuid.latencyCount++;
|
aggrGuid.latencyCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +294,6 @@ void StreamStatsModel::appendStreamStatsList(
|
|||||||
aggrAggr.txDuration = aggrGuid.txDuration;
|
aggrAggr.txDuration = aggrGuid.txDuration;
|
||||||
if (ss.rxLatency) {
|
if (ss.rxLatency) {
|
||||||
aggrAggr.latencySum += ss.rxLatency;
|
aggrAggr.latencySum += ss.rxLatency;
|
||||||
aggrAggr.jitterSum += ss.rxJitter;
|
|
||||||
aggrAggr.latencyCount++;
|
aggrAggr.latencyCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ private:
|
|||||||
quint64 rxBytes;
|
quint64 rxBytes;
|
||||||
quint64 txBytes;
|
quint64 txBytes;
|
||||||
quint64 rxLatency;
|
quint64 rxLatency;
|
||||||
quint64 rxJitter;
|
|
||||||
};
|
};
|
||||||
struct AggrGuidStats {
|
struct AggrGuidStats {
|
||||||
quint64 rxPkts;
|
quint64 rxPkts;
|
||||||
@ -68,7 +67,6 @@ private:
|
|||||||
qint64 pktLoss;
|
qint64 pktLoss;
|
||||||
double txDuration;
|
double txDuration;
|
||||||
quint64 latencySum;
|
quint64 latencySum;
|
||||||
quint64 jitterSum;
|
|
||||||
uint latencyCount;
|
uint latencyCount;
|
||||||
};
|
};
|
||||||
QList<Guid> guidList_;
|
QList<Guid> guidList_;
|
||||||
|
@ -46,10 +46,6 @@ StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent)
|
|||||||
streamStats->verticalHeader()->setHighlightSections(false);
|
streamStats->verticalHeader()->setHighlightSections(false);
|
||||||
streamStats->verticalHeader()->setDefaultSectionSize(
|
streamStats->verticalHeader()->setDefaultSectionSize(
|
||||||
streamStats->verticalHeader()->minimumSectionSize());
|
streamStats->verticalHeader()->minimumSectionSize());
|
||||||
|
|
||||||
// Fit all columns in window whenever data changes
|
|
||||||
connect(model, &QAbstractItemModel::modelReset,
|
|
||||||
[=]() { streamStats->resizeColumnsToContents(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamStatsWindow::~StreamStatsWindow()
|
StreamStatsWindow::~StreamStatsWindow()
|
||||||
@ -66,6 +62,4 @@ void StreamStatsWindow::on_actionShowDetails_triggered(bool checked)
|
|||||||
filterModel_->setFilterRegExp(QRegExp(".*"));
|
filterModel_->setFilterRegExp(QRegExp(".*"));
|
||||||
else
|
else
|
||||||
filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
|
filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
|
||||||
|
|
||||||
streamStats->resizeColumnsToContents();
|
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,6 @@
|
|||||||
<property name="contextMenuPolicy">
|
<property name="contextMenuPolicy">
|
||||||
<enum>Qt::ActionsContextMenu</enum>
|
<enum>Qt::ActionsContextMenu</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="selectionBehavior">
|
|
||||||
<enum>QAbstractItemView::SelectRows</enum>
|
|
||||||
</property>
|
|
||||||
<property name="whatsThis">
|
<property name="whatsThis">
|
||||||
<string>Oops! We don't seem to have any stream statistics for the requested port(s)
|
<string>Oops! We don't seem to have any stream statistics for the requested port(s)
|
||||||
|
|
||||||
|
@ -85,33 +85,20 @@ public:
|
|||||||
return toDouble(text, ok) * multiplier;
|
return toDouble(text, ok) * multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString toPktRateString(double pps) const
|
|
||||||
{
|
|
||||||
QString text;
|
|
||||||
|
|
||||||
if (pps >= 1e6)
|
|
||||||
return QObject::tr("%L1 Mpps").arg(pps/1e6, 0, 'f', 3);
|
|
||||||
|
|
||||||
if (pps >= 1e3)
|
|
||||||
return QObject::tr("%L1 Kpps").arg(pps/1e3, 0, 'f', 3);
|
|
||||||
|
|
||||||
return QObject::tr("%L1").arg(pps, 0, 'f', 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString toBitRateString(double bps) const
|
QString toBitRateString(double bps) const
|
||||||
{
|
{
|
||||||
QString text;
|
QString text;
|
||||||
|
|
||||||
if (bps >= 1e9)
|
if (bps >= 1e9)
|
||||||
return QObject::tr("%L1 Gbps").arg(bps/1e9, 0, 'f', 3);
|
return QObject::tr("%L1 Gbps").arg(bps/1e9, 0, 'f', 4);
|
||||||
|
|
||||||
if (bps >= 1e6)
|
if (bps >= 1e6)
|
||||||
return QObject::tr("%L1 Mbps").arg(bps/1e6, 0, 'f', 3);
|
return QObject::tr("%L1 Mbps").arg(bps/1e6, 0, 'f', 4);
|
||||||
|
|
||||||
if (bps >= 1e3)
|
if (bps >= 1e3)
|
||||||
return QObject::tr("%L1 Kbps").arg(bps/1e3, 0, 'f', 3);
|
return QObject::tr("%L1 Kbps").arg(bps/1e3, 0, 'f', 4);
|
||||||
|
|
||||||
return QObject::tr("%L1 bps").arg(bps, 0, 'f', 3);
|
return QObject::tr("%L1 bps").arg(bps, 0, 'f', 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString toTimeIntervalString(qint64 nanosecs) const
|
QString toTimeIntervalString(qint64 nanosecs) const
|
||||||
@ -119,13 +106,13 @@ public:
|
|||||||
QString text;
|
QString text;
|
||||||
|
|
||||||
if (nanosecs >= 1e9)
|
if (nanosecs >= 1e9)
|
||||||
return QObject::tr("%L1 s").arg(nanosecs/1e9, 0, 'f', 2);
|
return QObject::tr("%L1 s").arg(nanosecs/1e9, 0, 'f', 3);
|
||||||
|
|
||||||
if (nanosecs >= 1e6)
|
if (nanosecs >= 1e6)
|
||||||
return QObject::tr("%L1 ms").arg(nanosecs/1e6, 0, 'f', 2);
|
return QObject::tr("%L1 ms").arg(nanosecs/1e6, 0, 'f', 3);
|
||||||
|
|
||||||
if (nanosecs >= 1e3)
|
if (nanosecs >= 1e3)
|
||||||
return QObject::tr("%L1 us").arg(nanosecs/1e3, 0, 'f', 2);
|
return QObject::tr("%L1 us").arg(nanosecs/1e3, 0, 'f', 3);
|
||||||
|
|
||||||
return QObject::tr("%L1 ns").arg(nanosecs);
|
return QObject::tr("%L1 ns").arg(nanosecs);
|
||||||
}
|
}
|
||||||
|
@ -169,8 +169,7 @@ private:
|
|||||||
for (int i = start; i < end; i++)
|
for (int i = start; i < end; i++)
|
||||||
if (indexes.contains(model()->index(indexes.first().row(), i)))
|
if (indexes.contains(model()->index(indexes.first().row(), i)))
|
||||||
text.append(model()->headerData(i, Qt::Horizontal)
|
text.append(model()->headerData(i, Qt::Horizontal)
|
||||||
.toString().replace('\n', ' ')
|
.toString()+"\t");;
|
||||||
+"\t");;
|
|
||||||
text.append("\n");
|
text.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,14 +62,12 @@ void ArpProtocol::protoDataCopyFrom(const OstProto::Protocol &protocol)
|
|||||||
|
|
||||||
QString ArpProtocol::name() const
|
QString ArpProtocol::name() const
|
||||||
{
|
{
|
||||||
return isRarp() ?
|
return QString("Address Resolution Protocol");
|
||||||
QString("Reverse Address Resolution Protocol") :
|
|
||||||
QString("Address Resolution Protocol");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ArpProtocol::shortName() const
|
QString ArpProtocol::shortName() const
|
||||||
{
|
{
|
||||||
return isRarp() ? QString("RARP") : QString("ARP");
|
return QString("ARP");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -98,7 +96,7 @@ quint32 ArpProtocol::protocolId(ProtocolIdType type) const
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case ProtocolIdEth: return isRarp() ? 0x8035 : 0x0806;
|
case ProtocolIdEth: return 0x0806;
|
||||||
default:break;
|
default:break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -810,11 +808,3 @@ int ArpProtocol::protocolFrameVariableCount() const
|
|||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArpProtocol::isRarp() const
|
|
||||||
{
|
|
||||||
if ((data.op_code() == 3)
|
|
||||||
|| (data.op_code() ==4))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
@ -96,8 +96,6 @@ public:
|
|||||||
virtual int protocolFrameVariableCount() const;
|
virtual int protocolFrameVariableCount() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isRarp() const;
|
|
||||||
|
|
||||||
OstProto::Arp data;
|
OstProto::Arp data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,8 +30,6 @@ ArpConfigForm::ArpConfigForm(QWidget *parent)
|
|||||||
opCodeCombo->setValidator(new QIntValidator(0, 0xFFFF, this));
|
opCodeCombo->setValidator(new QIntValidator(0, 0xFFFF, this));
|
||||||
opCodeCombo->addItem(1, "ARP Request");
|
opCodeCombo->addItem(1, "ARP Request");
|
||||||
opCodeCombo->addItem(2, "ARP Reply");
|
opCodeCombo->addItem(2, "ARP Reply");
|
||||||
opCodeCombo->addItem(3, "Reverse ARP Request");
|
|
||||||
opCodeCombo->addItem(4, "Reverse ARP Reply");
|
|
||||||
|
|
||||||
connect(senderHwAddrMode, SIGNAL(currentIndexChanged(int)),
|
connect(senderHwAddrMode, SIGNAL(currentIndexChanged(int)),
|
||||||
SLOT(on_senderHwAddrMode_currentIndexChanged(int)));
|
SLOT(on_senderHwAddrMode_currentIndexChanged(int)));
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2022 Srivats P.
|
|
||||||
|
|
||||||
This file is part of "Ostinato"
|
|
||||||
|
|
||||||
This is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "fileformatoptions.h"
|
|
||||||
|
|
||||||
#include "pcapfileformat.h"
|
|
||||||
#include "pcapoptionsdialog.h"
|
|
||||||
#include "streamfileformat.h"
|
|
||||||
|
|
||||||
QDialog* FileFormatOptions::openOptionsDialog(StreamFileFormat *fileFormat)
|
|
||||||
{
|
|
||||||
if (dynamic_cast<PcapFileFormat*>(fileFormat))
|
|
||||||
return new PcapImportOptionsDialog(fileFormat->options());
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDialog* FileFormatOptions::saveOptionsDialog(StreamFileFormat* /*fileFormat*/)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDialog* FileFormatOptions::openOptionsDialog(SessionFileFormat* /*fileFormat*/)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDialog* FileFormatOptions::saveOptionsDialog(SessionFileFormat* /*fileFormat*/)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2022 Srivats P.
|
|
||||||
|
|
||||||
This file is part of "Ostinato"
|
|
||||||
|
|
||||||
This is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _FILE_FORMAT_OPTIONS_H
|
|
||||||
#define _FILE_FORMAT_OPTIONS_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
class SessionFileFormat;
|
|
||||||
class StreamFileFormat;
|
|
||||||
class QDialog;
|
|
||||||
|
|
||||||
class FileFormatOptions : QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
static QDialog* openOptionsDialog(StreamFileFormat *fileFormat);
|
|
||||||
static QDialog* saveOptionsDialog(StreamFileFormat *fileFormat);
|
|
||||||
|
|
||||||
static QDialog* openOptionsDialog(SessionFileFormat *fileFormat);
|
|
||||||
static QDialog* saveOptionsDialog(SessionFileFormat *fileFormat);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -214,6 +214,12 @@ Length (x4)</string>
|
|||||||
</item>
|
</item>
|
||||||
<item row="1" column="1" >
|
<item row="1" column="1" >
|
||||||
<widget class="QLineEdit" name="leIpSrcAddr" >
|
<widget class="QLineEdit" name="leIpSrcAddr" >
|
||||||
|
<property name="inputMask" >
|
||||||
|
<string>009.009.009.009; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text" >
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
<property name="alignment" >
|
<property name="alignment" >
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
@ -258,6 +264,12 @@ Length (x4)</string>
|
|||||||
<property name="enabled" >
|
<property name="enabled" >
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="inputMask" >
|
||||||
|
<string>009.009.009.009; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text" >
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" >
|
<item row="2" column="0" >
|
||||||
@ -269,6 +281,12 @@ Length (x4)</string>
|
|||||||
</item>
|
</item>
|
||||||
<item row="2" column="1" >
|
<item row="2" column="1" >
|
||||||
<widget class="QLineEdit" name="leIpDstAddr" >
|
<widget class="QLineEdit" name="leIpDstAddr" >
|
||||||
|
<property name="inputMask" >
|
||||||
|
<string>000.000.000.000; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text" >
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
<property name="alignment" >
|
<property name="alignment" >
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
@ -313,6 +331,12 @@ Length (x4)</string>
|
|||||||
<property name="enabled" >
|
<property name="enabled" >
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="inputMask" >
|
||||||
|
<string>009.009.009.009; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text" >
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "ip4config.h"
|
#include "ip4config.h"
|
||||||
#include "ip4.h"
|
#include "ip4.h"
|
||||||
#include "ipv4addressvalidator.h"
|
|
||||||
|
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
|
||||||
@ -31,10 +30,6 @@ Ip4ConfigForm::Ip4ConfigForm(QWidget *parent)
|
|||||||
leIpVersion->setValidator(new QIntValidator(0, 15, this));
|
leIpVersion->setValidator(new QIntValidator(0, 15, this));
|
||||||
leIpOptions->setValidator(new QRegExpValidator(QRegExp("[0-9a-fA-F]*"),
|
leIpOptions->setValidator(new QRegExpValidator(QRegExp("[0-9a-fA-F]*"),
|
||||||
this));
|
this));
|
||||||
leIpSrcAddr->setValidator(new IPv4AddressValidator(this));
|
|
||||||
leIpSrcAddrMask->setValidator(new IPv4AddressValidator(this));
|
|
||||||
leIpDstAddr->setValidator(new IPv4AddressValidator(this));
|
|
||||||
leIpDstAddrMask->setValidator(new IPv4AddressValidator(this));
|
|
||||||
|
|
||||||
connect(cmbIpSrcAddrMode, SIGNAL(currentIndexChanged(int)),
|
connect(cmbIpSrcAddrMode, SIGNAL(currentIndexChanged(int)),
|
||||||
this, SLOT(on_cmbIpSrcAddrMode_currentIndexChanged(int)));
|
this, SLOT(on_cmbIpSrcAddrMode_currentIndexChanged(int)));
|
||||||
|
@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "crc32c.h"
|
#include "crc32c.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QApplication>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
@ -437,19 +437,17 @@ _exit:
|
|||||||
|
|
||||||
void NativeFileFormat::initFileMetaData(OstProto::FileMetaData &metaData)
|
void NativeFileFormat::initFileMetaData(OstProto::FileMetaData &metaData)
|
||||||
{
|
{
|
||||||
QCoreApplication *app = QCoreApplication::instance();
|
|
||||||
|
|
||||||
// Fill in the "native" file format version
|
// Fill in the "native" file format version
|
||||||
metaData.set_format_version_major(kFileFormatVersionMajor);
|
metaData.set_format_version_major(kFileFormatVersionMajor);
|
||||||
metaData.set_format_version_minor(kFileFormatVersionMinor);
|
metaData.set_format_version_minor(kFileFormatVersionMinor);
|
||||||
metaData.set_format_version_revision(kFileFormatVersionRevision);
|
metaData.set_format_version_revision(kFileFormatVersionRevision);
|
||||||
|
|
||||||
metaData.set_generator_name(
|
metaData.set_generator_name(
|
||||||
app->applicationName().toUtf8().constData());
|
qApp->applicationName().toUtf8().constData());
|
||||||
metaData.set_generator_version(
|
metaData.set_generator_version(
|
||||||
app->property("version").toString().toUtf8().constData());
|
qApp->property("version").toString().toUtf8().constData());
|
||||||
metaData.set_generator_revision(
|
metaData.set_generator_revision(
|
||||||
app->property("revision").toString().toUtf8().constData());
|
qApp->property("revision").toString().toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeFileFormat::fileMetaSize(const quint8* file, int size)
|
int NativeFileFormat::fileMetaSize(const quint8* file, int size)
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
TEMPLATE = lib
|
|
||||||
CONFIG += qt staticlib
|
|
||||||
QT += network xml script
|
|
||||||
LIBS += \
|
|
||||||
-lprotobuf
|
|
||||||
|
|
||||||
PROTOS = \
|
|
||||||
fileformat.proto
|
|
||||||
|
|
||||||
HEADERS = \
|
|
||||||
ostprotolib.h \
|
|
||||||
nativefileformat.h \
|
|
||||||
ossnfileformat.h \
|
|
||||||
ostmfileformat.h \
|
|
||||||
pcapfileformat.h \
|
|
||||||
pdmlfileformat.h \
|
|
||||||
pythonfileformat.h \
|
|
||||||
pdmlprotocol.h \
|
|
||||||
pdmlprotocols.h \
|
|
||||||
pdmlreader.h \
|
|
||||||
sessionfileformat.h \
|
|
||||||
streamfileformat.h
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
ostprotolib.cpp \
|
|
||||||
nativefileformat.cpp \
|
|
||||||
ossnfileformat.cpp \
|
|
||||||
ostmfileformat.cpp \
|
|
||||||
pcapfileformat.cpp \
|
|
||||||
pdmlfileformat.cpp \
|
|
||||||
pythonfileformat.cpp \
|
|
||||||
pdmlprotocol.cpp \
|
|
||||||
pdmlprotocols.cpp \
|
|
||||||
pdmlreader.cpp \
|
|
||||||
sessionfileformat.cpp \
|
|
||||||
streamfileformat.cpp \
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
vlanpdml.cpp \
|
|
||||||
svlanpdml.cpp \
|
|
||||||
stppdml.cpp \
|
|
||||||
eth2pdml.cpp \
|
|
||||||
llcpdml.cpp \
|
|
||||||
arppdml.cpp \
|
|
||||||
ip4pdml.cpp \
|
|
||||||
ip6pdml.cpp \
|
|
||||||
grepdml.cpp \
|
|
||||||
icmppdml.cpp \
|
|
||||||
icmp6pdml.cpp \
|
|
||||||
igmppdml.cpp \
|
|
||||||
mldpdml.cpp \
|
|
||||||
tcppdml.cpp \
|
|
||||||
udppdml.cpp \
|
|
||||||
textprotopdml.cpp \
|
|
||||||
samplepdml.cpp
|
|
||||||
|
|
||||||
QMAKE_DISTCLEAN += object_script.*
|
|
||||||
|
|
||||||
include(../protobuf.pri)
|
|
||||||
include(../options.pri)
|
|
@ -1,15 +0,0 @@
|
|||||||
TEMPLATE = lib
|
|
||||||
CONFIG += qt staticlib
|
|
||||||
QT += widgets
|
|
||||||
|
|
||||||
FORMS = \
|
|
||||||
pcapfileimport.ui
|
|
||||||
|
|
||||||
HEADERS = \
|
|
||||||
fileformatoptions.h \
|
|
||||||
pcapoptionsdialog.h
|
|
||||||
|
|
||||||
SOURCES = \
|
|
||||||
fileformatoptions.cpp \
|
|
||||||
pcapoptionsdialog.cpp
|
|
||||||
|
|
@ -2,6 +2,11 @@ TEMPLATE = lib
|
|||||||
CONFIG += qt staticlib
|
CONFIG += qt staticlib
|
||||||
QT += widgets network xml script
|
QT += widgets network xml script
|
||||||
INCLUDEPATH += "../extra/qhexedit2/src"
|
INCLUDEPATH += "../extra/qhexedit2/src"
|
||||||
|
LIBS += \
|
||||||
|
-lprotobuf
|
||||||
|
|
||||||
|
FORMS = \
|
||||||
|
pcapfileimport.ui \
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
mac.ui \
|
mac.ui \
|
||||||
@ -27,10 +32,28 @@ FORMS += \
|
|||||||
sign.ui \
|
sign.ui \
|
||||||
userscript.ui
|
userscript.ui
|
||||||
|
|
||||||
|
PROTOS = \
|
||||||
|
fileformat.proto
|
||||||
|
|
||||||
|
# TODO: Move fileformat related stuff into a different library - why?
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
|
ostprotolib.h \
|
||||||
ipv4addressdelegate.h \
|
ipv4addressdelegate.h \
|
||||||
ipv6addressdelegate.h \
|
ipv6addressdelegate.h \
|
||||||
spinboxdelegate.h \
|
nativefileformat.h \
|
||||||
|
ossnfileformat.h \
|
||||||
|
ostmfileformat.h \
|
||||||
|
pcapfileformat.h \
|
||||||
|
pdmlfileformat.h \
|
||||||
|
pythonfileformat.h \
|
||||||
|
pdmlprotocol.h \
|
||||||
|
pdmlprotocols.h \
|
||||||
|
pdmlreader.h \
|
||||||
|
sessionfileformat.h \
|
||||||
|
streamfileformat.h \
|
||||||
|
spinboxdelegate.h
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
tosdscp.h
|
tosdscp.h
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
@ -67,7 +90,21 @@ HEADERS += \
|
|||||||
userscriptconfig.h
|
userscriptconfig.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
spinboxdelegate.cpp \
|
ostprotolib.cpp \
|
||||||
|
nativefileformat.cpp \
|
||||||
|
ossnfileformat.cpp \
|
||||||
|
ostmfileformat.cpp \
|
||||||
|
pcapfileformat.cpp \
|
||||||
|
pdmlfileformat.cpp \
|
||||||
|
pythonfileformat.cpp \
|
||||||
|
pdmlprotocol.cpp \
|
||||||
|
pdmlprotocols.cpp \
|
||||||
|
pdmlreader.cpp \
|
||||||
|
sessionfileformat.cpp \
|
||||||
|
streamfileformat.cpp \
|
||||||
|
spinboxdelegate.cpp
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
tosdscp.cpp
|
tosdscp.cpp
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@ -96,6 +133,26 @@ SOURCES += \
|
|||||||
signconfig.cpp \
|
signconfig.cpp \
|
||||||
userscriptconfig.cpp
|
userscriptconfig.cpp
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
vlanpdml.cpp \
|
||||||
|
svlanpdml.cpp \
|
||||||
|
stppdml.cpp \
|
||||||
|
eth2pdml.cpp \
|
||||||
|
llcpdml.cpp \
|
||||||
|
arppdml.cpp \
|
||||||
|
ip4pdml.cpp \
|
||||||
|
ip6pdml.cpp \
|
||||||
|
grepdml.cpp \
|
||||||
|
icmppdml.cpp \
|
||||||
|
icmp6pdml.cpp \
|
||||||
|
igmppdml.cpp \
|
||||||
|
mldpdml.cpp \
|
||||||
|
tcppdml.cpp \
|
||||||
|
udppdml.cpp \
|
||||||
|
textprotopdml.cpp \
|
||||||
|
samplepdml.cpp
|
||||||
|
|
||||||
QMAKE_DISTCLEAN += object_script.*
|
QMAKE_DISTCLEAN += object_script.*
|
||||||
|
|
||||||
|
include(../protobuf.pri)
|
||||||
include(../options.pri)
|
include(../options.pri)
|
||||||
|
@ -78,7 +78,6 @@ const quint16 kIp4EthType = 0x0800;
|
|||||||
const quint16 kIp6EthType = 0x86dd;
|
const quint16 kIp6EthType = 0x86dd;
|
||||||
const quint16 kMplsEthType = 0x8847;
|
const quint16 kMplsEthType = 0x8847;
|
||||||
const QSet<quint16> kVlanEthTypes = {0x8100, 0x9100, 0x88a8};
|
const QSet<quint16> kVlanEthTypes = {0x8100, 0x9100, 0x88a8};
|
||||||
const uint kEthOverhead = 20;
|
|
||||||
|
|
||||||
// VLAN
|
// VLAN
|
||||||
const quint16 kVlanTagSize = 4;
|
const quint16 kVlanTagSize = 4;
|
||||||
|
@ -42,6 +42,38 @@ const quint32 kDltEthernet = 1;
|
|||||||
|
|
||||||
PcapFileFormat pcapFileFormat;
|
PcapFileFormat pcapFileFormat;
|
||||||
|
|
||||||
|
PcapImportOptionsDialog::PcapImportOptionsDialog(QVariantMap *options)
|
||||||
|
: QDialog(NULL)
|
||||||
|
{
|
||||||
|
setupUi(this);
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
options_ = options;
|
||||||
|
|
||||||
|
viaPdml->setChecked(options_->value("ViaPdml").toBool());
|
||||||
|
// XXX: By default this key is absent - so that pcap import tests
|
||||||
|
// evaluate to false and hence show minimal diffs.
|
||||||
|
// However, for the GUI user, this should be enabled by default.
|
||||||
|
recalculateCksums->setChecked(
|
||||||
|
options_->value("RecalculateCksums", QVariant(true))
|
||||||
|
.toBool());
|
||||||
|
doDiff->setChecked(options_->value("DoDiff").toBool());
|
||||||
|
|
||||||
|
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
|
}
|
||||||
|
|
||||||
|
PcapImportOptionsDialog::~PcapImportOptionsDialog()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PcapImportOptionsDialog::accept()
|
||||||
|
{
|
||||||
|
options_->insert("ViaPdml", viaPdml->isChecked());
|
||||||
|
options_->insert("RecalculateCksums", recalculateCksums->isChecked());
|
||||||
|
options_->insert("DoDiff", doDiff->isChecked());
|
||||||
|
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
|
||||||
PcapFileFormat::PcapFileFormat()
|
PcapFileFormat::PcapFileFormat()
|
||||||
{
|
{
|
||||||
importOptions_.insert("ViaPdml", true);
|
importOptions_.insert("ViaPdml", true);
|
||||||
@ -431,7 +463,7 @@ _retry:
|
|||||||
diffFile.close();
|
diffFile.close();
|
||||||
if (diffFile.size())
|
if (diffFile.size())
|
||||||
{
|
{
|
||||||
error.append(tr("<p>There is a diff between the original and imported streams. See details to review the diff.</p><p>💡 If you don't need to edit packets, you can retry the import and uncheck the Intelligent Import option.</p><p>Why a diff? See <a href='%1'>possible reasons</a>.</p>\n\n\n\n").arg("https://jump.ostinato.org/pcapdiff"));
|
error.append(tr("<p>There is a diff between the original and imported streams. See details to review the diff.</p><p>Why a diff? See <a href='%1'>possible reasons</a>.</p>\n\n\n\n").arg("https://jump.ostinato.org/pcapdiff"));
|
||||||
diffFile.open();
|
diffFile.open();
|
||||||
diffFile.seek(0);
|
diffFile.seek(0);
|
||||||
error.append(QString(diffFile.readAll()));
|
error.append(QString(diffFile.readAll()));
|
||||||
@ -699,9 +731,9 @@ _exit:
|
|||||||
return isOk;
|
return isOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap* PcapFileFormat::options()
|
QDialog* PcapFileFormat::openOptionsDialog()
|
||||||
{
|
{
|
||||||
return &importOptions_;
|
return new PcapImportOptionsDialog(&importOptions_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PcapFileFormat::isMyFileFormat(const QString /*fileName*/)
|
bool PcapFileFormat::isMyFileFormat(const QString /*fileName*/)
|
||||||
|
@ -20,10 +20,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#define _PCAP_FILE_FORMAT_H
|
#define _PCAP_FILE_FORMAT_H
|
||||||
|
|
||||||
#include "streamfileformat.h"
|
#include "streamfileformat.h"
|
||||||
|
#include "ui_pcapfileimport.h"
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
class PcapImportOptionsDialog: public QDialog, public Ui::PcapFileImport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PcapImportOptionsDialog(QVariantMap *options);
|
||||||
|
~PcapImportOptionsDialog();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void accept();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVariantMap *options_;
|
||||||
|
};
|
||||||
|
|
||||||
class PdmlReader;
|
class PdmlReader;
|
||||||
class PcapFileFormat : public StreamFileFormat
|
class PcapFileFormat : public StreamFileFormat
|
||||||
{
|
{
|
||||||
@ -38,7 +52,7 @@ public:
|
|||||||
bool save(const OstProto::StreamConfigList streams,
|
bool save(const OstProto::StreamConfigList streams,
|
||||||
const QString fileName, QString &error);
|
const QString fileName, QString &error);
|
||||||
|
|
||||||
virtual QVariantMap* options();
|
virtual QDialog* openOptionsDialog();
|
||||||
|
|
||||||
bool isMyFileFormat(const QString fileName);
|
bool isMyFileFormat(const QString fileName);
|
||||||
bool isMyFileType(const QString fileType);
|
bool isMyFileType(const QString fileType);
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2011 Srivats P.
|
|
||||||
|
|
||||||
This file is part of "Ostinato"
|
|
||||||
|
|
||||||
This is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "pcapoptionsdialog.h"
|
|
||||||
|
|
||||||
PcapImportOptionsDialog::PcapImportOptionsDialog(QVariantMap *options)
|
|
||||||
: QDialog(NULL)
|
|
||||||
{
|
|
||||||
Q_ASSERT(options != NULL);
|
|
||||||
|
|
||||||
setupUi(this);
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
options_ = options;
|
|
||||||
|
|
||||||
viaPdml->setChecked(options_->value("ViaPdml").toBool());
|
|
||||||
// XXX: By default this key is absent - so that pcap import tests
|
|
||||||
// evaluate to false and hence show minimal diffs.
|
|
||||||
// However, for the GUI user, this should be enabled by default.
|
|
||||||
recalculateCksums->setChecked(
|
|
||||||
options_->value("RecalculateCksums", QVariant(true))
|
|
||||||
.toBool());
|
|
||||||
doDiff->setChecked(options_->value("DoDiff").toBool());
|
|
||||||
|
|
||||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
|
||||||
}
|
|
||||||
|
|
||||||
PcapImportOptionsDialog::~PcapImportOptionsDialog()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void PcapImportOptionsDialog::accept()
|
|
||||||
{
|
|
||||||
options_->insert("ViaPdml", viaPdml->isChecked());
|
|
||||||
options_->insert("RecalculateCksums", recalculateCksums->isChecked());
|
|
||||||
options_->insert("DoDiff", doDiff->isChecked());
|
|
||||||
|
|
||||||
QDialog::accept();
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2011 Srivats P.
|
|
||||||
|
|
||||||
This file is part of "Ostinato"
|
|
||||||
|
|
||||||
This is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
#ifndef _PCAP_OPTIONS_DIALOG_H
|
|
||||||
#define _PCAP_OPTIONS_DIALOG_H
|
|
||||||
|
|
||||||
#include "ui_pcapfileimport.h"
|
|
||||||
|
|
||||||
#include <QVariantMap>
|
|
||||||
|
|
||||||
class PcapImportOptionsDialog: public QDialog, public Ui::PcapFileImport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PcapImportOptionsDialog(QVariantMap *options);
|
|
||||||
~PcapImportOptionsDialog();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void accept();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QVariantMap *options_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -293,7 +293,6 @@ message StreamStats {
|
|||||||
|
|
||||||
optional double tx_duration = 3; // in seconds
|
optional double tx_duration = 3; // in seconds
|
||||||
optional uint64 latency = 4; // in nanoseconds
|
optional uint64 latency = 4; // in nanoseconds
|
||||||
optional uint64 jitter = 5; // in nanoseconds
|
|
||||||
|
|
||||||
optional uint64 rx_pkts = 11;
|
optional uint64 rx_pkts = 11;
|
||||||
optional uint64 rx_bytes = 12;
|
optional uint64 rx_bytes = 12;
|
||||||
|
@ -32,7 +32,12 @@ SessionFileFormat::~SessionFileFormat()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap* SessionFileFormat::options()
|
QDialog* SessionFileFormat::openOptionsDialog()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog* SessionFileFormat::saveOptionsDialog()
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "fileformat.pb.h"
|
#include "fileformat.pb.h"
|
||||||
#include "protocol.pb.h"
|
#include "protocol.pb.h"
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QVariantMap>
|
#include <QString>
|
||||||
|
|
||||||
|
class QDialog;
|
||||||
|
|
||||||
class SessionFileFormat : public QThread
|
class SessionFileFormat : public QThread
|
||||||
{
|
{
|
||||||
@ -41,7 +42,8 @@ public:
|
|||||||
virtual bool save(const OstProto::SessionContent &session,
|
virtual bool save(const OstProto::SessionContent &session,
|
||||||
const QString fileName, QString &error) = 0;
|
const QString fileName, QString &error) = 0;
|
||||||
|
|
||||||
virtual QVariantMap* options();
|
virtual QDialog* openOptionsDialog();
|
||||||
|
virtual QDialog* saveOptionsDialog();
|
||||||
|
|
||||||
void openAsync(const QString fileName,
|
void openAsync(const QString fileName,
|
||||||
OstProto::SessionContent &session, QString &error);
|
OstProto::SessionContent &session, QString &error);
|
||||||
|
@ -285,9 +285,7 @@ bool SignProtocol::packetTtagId(const uchar *pkt, int pktLen, uint *ttagId, uint
|
|||||||
} else if (*p == kTypeLenGuid) {
|
} else if (*p == kTypeLenGuid) {
|
||||||
*guid = qFromBigEndian<quint32>(p - 3) >> 8;
|
*guid = qFromBigEndian<quint32>(p - 3) >> 8;
|
||||||
} else if (*p == kTypeLenTxPort) {
|
} else if (*p == kTypeLenTxPort) {
|
||||||
#ifdef Q_OS_WIN32
|
|
||||||
*ttagId |= uint(*(p - 1)) << 8;
|
*ttagId |= uint(*(p - 1)) << 8;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
p -= 1 + (*p >> 5); // move to next TLV
|
p -= 1 + (*p >> 5); // move to next TLV
|
||||||
}
|
}
|
||||||
|
@ -41,19 +41,12 @@ TLVs are encoded as
|
|||||||
Len does NOT include the one byte of TypeLen
|
Len does NOT include the one byte of TypeLen
|
||||||
Size of the value field varies between 0 to 7 bytes
|
Size of the value field varies between 0 to 7 bytes
|
||||||
|
|
||||||
Defined TLVs
|
Defined TLVs
|
||||||
Type = 0, Len = 0 (0x00): End of TLVs
|
Type = 0, Len = 0 (0x00): End of TLVs
|
||||||
Type = 1, Len = 3 (0x61): Stream GUID
|
Type = 1, Len = 3 (0x61): Stream GUID
|
||||||
Type = 2, Len = 1 (0x22): T-Tag Placeholder (0 value)
|
Type = 2, Len = 1 (0x22): T-Tag Placeholder (0 value)
|
||||||
Type = 3, Len = 1 (0x23): T-Tag with actual value
|
Type = 3, Len = 1 (0x23): T-Tag with actual value
|
||||||
Type = 4, Len = 1 (0x24): Tx Port Id
|
Type = 4, Len = 1 (0x24): Tx Port Id
|
||||||
|
|
||||||
Order of TLVs from end of packet towards beginning [Offset, Size]
|
|
||||||
[ -4, 4 bytes] Magic
|
|
||||||
[ -6, 2 bytes] TTag (Placeholder or actual)
|
|
||||||
[-10, 4 bytes] Stream Guid
|
|
||||||
[-12, 2 bytes] Tx Port Id
|
|
||||||
[-13, 1 byte ] End
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SignProtocol : public AbstractProtocol
|
class SignProtocol : public AbstractProtocol
|
||||||
|
@ -684,7 +684,6 @@ bool StreamBase::preflightCheck(QStringList &result) const
|
|||||||
bool chkShort = true;
|
bool chkShort = true;
|
||||||
bool chkTrunc = true;
|
bool chkTrunc = true;
|
||||||
bool chkJumbo = true;
|
bool chkJumbo = true;
|
||||||
bool chkSignIcmp = true;
|
|
||||||
int count = isFrameSizeVariable() ? frameSizeVariableCount() : 1;
|
int count = isFrameSizeVariable() ? frameSizeVariableCount() : 1;
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
@ -702,17 +701,6 @@ bool StreamBase::preflightCheck(QStringList &result) const
|
|||||||
pass = false;
|
pass = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chkSignIcmp && hasProtocol(OstProto::Protocol::kSignFieldNumber)
|
|
||||||
&& hasProtocol(OstProto::Protocol::kIcmpFieldNumber))
|
|
||||||
{
|
|
||||||
result << QObject::tr("Stream statistics are not supported "
|
|
||||||
"for ICMP packets - please use a non-ICMP protocol or "
|
|
||||||
"remove special signature from ICMP streams");
|
|
||||||
chkSignIcmp = false;
|
|
||||||
pass = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (chkTrunc && (pktLen < (frameProtocolLength(i) + kFcsSize)))
|
if (chkTrunc && (pktLen < (frameProtocolLength(i) + kFcsSize)))
|
||||||
{
|
{
|
||||||
result << QObject::tr("One or more frames may be truncated - "
|
result << QObject::tr("One or more frames may be truncated - "
|
||||||
|
@ -35,7 +35,12 @@ StreamFileFormat::~StreamFileFormat()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap* StreamFileFormat::options()
|
QDialog* StreamFileFormat::openOptionsDialog()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog* StreamFileFormat::saveOptionsDialog()
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,8 @@ public:
|
|||||||
virtual bool save(const OstProto::StreamConfigList streams,
|
virtual bool save(const OstProto::StreamConfigList streams,
|
||||||
const QString fileName, QString &error) = 0;
|
const QString fileName, QString &error) = 0;
|
||||||
|
|
||||||
virtual QVariantMap* options();
|
virtual QDialog* openOptionsDialog();
|
||||||
|
virtual QDialog* saveOptionsDialog();
|
||||||
|
|
||||||
void openAsync(const QString fileName,
|
void openAsync(const QString fileName,
|
||||||
OstProto::StreamConfigList &streams, QString &error);
|
OstProto::StreamConfigList &streams, QString &error);
|
||||||
|
@ -32,8 +32,6 @@ Updater::Updater()
|
|||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// Tests!
|
// Tests!
|
||||||
Q_ASSERT(isVersionNewer("1.3.0", "1.2.0") == true);
|
|
||||||
Q_ASSERT(isVersionNewer("1.3.0", "1.1") == true);
|
|
||||||
Q_ASSERT(isVersionNewer("1.2.0", "1.1") == true);
|
Q_ASSERT(isVersionNewer("1.2.0", "1.1") == true);
|
||||||
Q_ASSERT(isVersionNewer("1.1", "1") == true);
|
Q_ASSERT(isVersionNewer("1.1", "1") == true);
|
||||||
Q_ASSERT(isVersionNewer("10.1", "2") == true);
|
Q_ASSERT(isVersionNewer("10.1", "2") == true);
|
||||||
|
10
ost.pro
10
ost.pro
@ -1,20 +1,14 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
SUBDIRS = client server ostfile ostfilegui ostproto ostprotogui rpc extra
|
SUBDIRS = client server ostproto ostprotogui rpc extra
|
||||||
|
|
||||||
client.target = client
|
client.target = client
|
||||||
client.file = client/ostinato.pro
|
client.file = client/ostinato.pro
|
||||||
client.depends = ostfile ostfilegui ostproto ostprotogui rpc extra
|
client.depends = ostproto ostprotogui rpc extra
|
||||||
|
|
||||||
server.target = server
|
server.target = server
|
||||||
server.file = server/drone.pro
|
server.file = server/drone.pro
|
||||||
server.depends = ostproto rpc
|
server.depends = ostproto rpc
|
||||||
|
|
||||||
ostfile.file = common/ostfile.pro
|
|
||||||
ostfile.depends = ostproto
|
|
||||||
|
|
||||||
ostfilegui.file = common/ostfilegui.pro
|
|
||||||
ostfilegui.depends = ostfile
|
|
||||||
|
|
||||||
ostproto.file = common/ostproto.pro
|
ostproto.file = common/ostproto.pro
|
||||||
|
|
||||||
ostprotogui.file = common/ostprotogui.pro
|
ostprotogui.file = common/ostprotogui.pro
|
||||||
|
@ -21,11 +21,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "../common/abstractprotocol.h"
|
#include "../common/abstractprotocol.h"
|
||||||
#include "../common/framevalueattrib.h"
|
#include "../common/framevalueattrib.h"
|
||||||
#include "../common/packet.h"
|
|
||||||
#include "../common/streambase.h"
|
#include "../common/streambase.h"
|
||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
#include "interfaceinfo.h"
|
#include "interfaceinfo.h"
|
||||||
#include "packetbuffer.h"
|
#include "packetbuffer.h"
|
||||||
|
#include "streamtiming.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QIODevice>
|
#include <QIODevice>
|
||||||
@ -245,7 +245,6 @@ int AbstractPort::updatePacketListSequential()
|
|||||||
quint64 duration = 0; // in nanosec
|
quint64 duration = 0; // in nanosec
|
||||||
quint64 totalPkts = 0;
|
quint64 totalPkts = 0;
|
||||||
QList<uint> ttagMarkers;
|
QList<uint> ttagMarkers;
|
||||||
uint ttagRepeatInterval;
|
|
||||||
FrameValueAttrib packetListAttrib;
|
FrameValueAttrib packetListAttrib;
|
||||||
long sec = 0;
|
long sec = 0;
|
||||||
long nsec = 0;
|
long nsec = 0;
|
||||||
@ -342,8 +341,7 @@ int AbstractPort::updatePacketListSequential()
|
|||||||
|
|
||||||
if (n >= 1) {
|
if (n >= 1) {
|
||||||
loopNextPacketSet(x, n, 0, loopDelay);
|
loopNextPacketSet(x, n, 0, loopDelay);
|
||||||
qDebug("PacketSet: n = %lu, x = %lu, delay = %llu ns",
|
qDebug("PacketSet: n = %lu, x = %lu", n, x);
|
||||||
n, x, loopDelay);
|
|
||||||
}
|
}
|
||||||
else if (n == 0)
|
else if (n == 0)
|
||||||
x = 0;
|
x = 0;
|
||||||
@ -365,8 +363,7 @@ int AbstractPort::updatePacketListSequential()
|
|||||||
// Create a packet set for 'y' with repeat = 1
|
// Create a packet set for 'y' with repeat = 1
|
||||||
if (j == x) {
|
if (j == x) {
|
||||||
loopNextPacketSet(y, 1, 0, loopDelay);
|
loopNextPacketSet(y, 1, 0, loopDelay);
|
||||||
qDebug("PacketSet: n = 1, y = %lu, delay = %llu",
|
qDebug("PacketSet: n = 1, y = %lu", y);
|
||||||
y, loopDelay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug("q(%d, %d) sec = %lu nsec = %lu",
|
qDebug("q(%d, %d) sec = %lu nsec = %lu",
|
||||||
@ -402,18 +399,6 @@ int AbstractPort::updatePacketListSequential()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loopDelay == 0 implies 0 pps i.e. top speed
|
|
||||||
// For ttag calc/config below we need loopDelay to be non-zero,
|
|
||||||
// so we re-calc based on max line rate (speed). If we don't
|
|
||||||
// have the actual port speed, we assume 1000 Mbps
|
|
||||||
if (loopDelay == 0) {
|
|
||||||
double maxSpeed = data_.speed() ? data_.speed(): 1000;
|
|
||||||
double maxPktRate = (maxSpeed*1e6)
|
|
||||||
/(8*(streamList_[i]->frameLenAvg()
|
|
||||||
+ Packet::kEthOverhead));
|
|
||||||
loopDelay = 1e9/maxPktRate; // in nanosec
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a Ttag marker after every kTtagTimeInterval_ worth of pkts
|
// Add a Ttag marker after every kTtagTimeInterval_ worth of pkts
|
||||||
if (hasTtag) {
|
if (hasTtag) {
|
||||||
uint ttagPktInterval = kTtagTimeInterval_*1e9/loopDelay;
|
uint ttagPktInterval = kTtagTimeInterval_*1e9/loopDelay;
|
||||||
@ -441,10 +426,9 @@ int AbstractPort::updatePacketListSequential()
|
|||||||
returnToQIdx = 0;
|
returnToQIdx = 0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// XXX: no list loop delay required since we don't create
|
setPacketListLoopMode(true, 0,
|
||||||
// any implicit packet sets now
|
streamList_[i]->sendUnit() ==
|
||||||
setPacketListLoopMode(true, 0, 0);
|
StreamBase::e_su_bursts ? ibg1 : ipg1);
|
||||||
qDebug("Seq mode list loop true with 0 delay");
|
|
||||||
goto _stop_no_more_pkts;
|
goto _stop_no_more_pkts;
|
||||||
|
|
||||||
case StreamBase::e_nw_goto_next:
|
case StreamBase::e_nw_goto_next:
|
||||||
@ -459,17 +443,12 @@ int AbstractPort::updatePacketListSequential()
|
|||||||
} // if (stream is enabled)
|
} // if (stream is enabled)
|
||||||
} // for (numStreams)
|
} // for (numStreams)
|
||||||
|
|
||||||
|
_out_of_memory:
|
||||||
_stop_no_more_pkts:
|
_stop_no_more_pkts:
|
||||||
// See comments in updatePacketListInterleaved() for calc explanation
|
// See comments in updatePacketListInterleaved() for calc explanation
|
||||||
ttagRepeatInterval = ttagMarkers.isEmpty() ? 0 :
|
setPacketListTtagMarkers(ttagMarkers, ttagMarkers.isEmpty() ? 0 :
|
||||||
qMax(uint(kTtagTimeInterval_*1e9/(duration)), 1U)
|
qMax(uint(kTtagTimeInterval_*1e9/(duration)),
|
||||||
* totalPkts;
|
1U) * totalPkts);
|
||||||
if (!setPacketListTtagMarkers(ttagMarkers, ttagRepeatInterval)) {
|
|
||||||
clearPacketList(); // don't leave it half baked/inconsitent
|
|
||||||
packetListAttrib.errorFlags |= FrameValueAttrib::OutOfMemoryError;
|
|
||||||
}
|
|
||||||
|
|
||||||
_out_of_memory:
|
|
||||||
isSendQueueDirty_ = false;
|
isSendQueueDirty_ = false;
|
||||||
|
|
||||||
qDebug("PacketListAttrib = %x",
|
qDebug("PacketListAttrib = %x",
|
||||||
@ -653,7 +632,6 @@ int AbstractPort::updatePacketListInterleaved()
|
|||||||
// i.e. send all streams "simultaneously" as fast as possible
|
// i.e. send all streams "simultaneously" as fast as possible
|
||||||
// as a result all streams will be at the same rate e.g. for 2 streams,
|
// as a result all streams will be at the same rate e.g. for 2 streams,
|
||||||
// it would 50% each; for 3 streams - all at 33.3% and so on
|
// it would 50% each; for 3 streams - all at 33.3% and so on
|
||||||
// FIXME: Should we calc minGap based on max line rate and avg pkt size?
|
|
||||||
if (minGap == ULLONG_MAX) {
|
if (minGap == ULLONG_MAX) {
|
||||||
minGap = 1;
|
minGap = 1;
|
||||||
duration = 1;
|
duration = 1;
|
||||||
@ -679,11 +657,12 @@ int AbstractPort::updatePacketListInterleaved()
|
|||||||
// Count total packets we are going to add, so that we can create
|
// Count total packets we are going to add, so that we can create
|
||||||
// an explicit packet set first
|
// an explicit packet set first
|
||||||
// TODO: Find less expensive way to do this counting
|
// TODO: Find less expensive way to do this counting
|
||||||
|
// FIXME: Turbo still thinks it has to create implicit packet set for
|
||||||
|
// interleaved mode - Turbo code should be changed once this is validated
|
||||||
quint64 totalPkts = 0;
|
quint64 totalPkts = 0;
|
||||||
QVector<ulong> ttagSchedSec(numStreams, 0);
|
QVector<ulong> ttagSchedSec(numStreams, 0);
|
||||||
QVector<ulong> ttagSchedNsec(numStreams, 0);
|
QVector<ulong> ttagSchedNsec(numStreams, 0);
|
||||||
QList<uint> ttagMarkers;
|
QList<uint> ttagMarkers;
|
||||||
uint ttagRepeatInterval;
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -736,23 +715,16 @@ int AbstractPort::updatePacketListInterleaved()
|
|||||||
}
|
}
|
||||||
} while ((sec < durSec) || ((sec == durSec) && (nsec < durNsec)));
|
} while ((sec < durSec) || ((sec == durSec) && (nsec < durNsec)));
|
||||||
|
|
||||||
qint64 delaySec = durSec - lastPktTxSec;
|
|
||||||
qint64 delayNsec = durNsec - lastPktTxNsec;
|
|
||||||
while (delayNsec < 0)
|
|
||||||
{
|
|
||||||
delayNsec += long(1e9);
|
|
||||||
delaySec--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: For interleaved mode, we ALWAYS have a single packet set with
|
// XXX: For interleaved mode, we ALWAYS have a single packet set with
|
||||||
// one repeat
|
// one repeat and 0n set loop delay
|
||||||
loopNextPacketSet(totalPkts, 1, delaySec, delayNsec);
|
loopNextPacketSet(totalPkts, 1, 0, 0);
|
||||||
qDebug("Interleaved single PacketSet of size %lld, duration %llu.%09llu "
|
qDebug("Interleaved single PacketSet of size %lld, duration %llu.%09llu "
|
||||||
"repeat 1 and delay %lld.%09lld",
|
"repeat 1 and delay 0",
|
||||||
totalPkts, durSec, durNsec, delaySec, delayNsec);
|
totalPkts, durSec, durNsec);
|
||||||
|
|
||||||
// Reset working sched/counts before building the packet list
|
// Reset working sched/counts before building the packet list
|
||||||
sec = nsec = 0;
|
sec = nsec = 0;
|
||||||
|
lastPktTxSec = lastPktTxNsec = 0;
|
||||||
for (int i = 0; i < numStreams; i++)
|
for (int i = 0; i < numStreams; i++)
|
||||||
{
|
{
|
||||||
schedSec[i] = 0;
|
schedSec[i] = 0;
|
||||||
@ -795,6 +767,8 @@ int AbstractPort::updatePacketListInterleaved()
|
|||||||
packetListAttrib.errorFlags |= FrameValueAttrib::OutOfMemoryError;
|
packetListAttrib.errorFlags |= FrameValueAttrib::OutOfMemoryError;
|
||||||
goto _out_of_memory;
|
goto _out_of_memory;
|
||||||
}
|
}
|
||||||
|
lastPktTxSec = sec;
|
||||||
|
lastPktTxNsec = nsec;
|
||||||
|
|
||||||
pktCount[i]++;
|
pktCount[i]++;
|
||||||
schedNsec[i] += (pktCount.at(i) < np1.at(i)) ?
|
schedNsec[i] += (pktCount.at(i) < np1.at(i)) ?
|
||||||
@ -824,9 +798,17 @@ int AbstractPort::updatePacketListInterleaved()
|
|||||||
}
|
}
|
||||||
} while ((sec < durSec) || ((sec == durSec) && (nsec < durNsec)));
|
} while ((sec < durSec) || ((sec == durSec) && (nsec < durNsec)));
|
||||||
|
|
||||||
// XXX: The single packet has the delay, so no list loop delay required
|
{
|
||||||
// XXX: Both seq/interleaved mode no longer use list loop delay!
|
qint64 delaySec = durSec - lastPktTxSec;
|
||||||
setPacketListLoopMode(true, 0, 0);
|
qint64 delayNsec = durNsec - lastPktTxNsec;
|
||||||
|
while (delayNsec < 0)
|
||||||
|
{
|
||||||
|
delayNsec += long(1e9);
|
||||||
|
delaySec--;
|
||||||
|
}
|
||||||
|
qDebug("loop Delay = %lld.%09lld", delaySec, delayNsec);
|
||||||
|
setPacketListLoopMode(true, delaySec, delayNsec);
|
||||||
|
}
|
||||||
|
|
||||||
// XXX: TTag repeat interval calculation:
|
// XXX: TTag repeat interval calculation:
|
||||||
// CASE 1. pktListDuration < kTtagTimeInterval:
|
// CASE 1. pktListDuration < kTtagTimeInterval:
|
||||||
@ -835,13 +817,10 @@ int AbstractPort::updatePacketListInterleaved()
|
|||||||
// CASE 2. pktListDuration > kTtagTimeInterval:
|
// CASE 2. pktListDuration > kTtagTimeInterval:
|
||||||
// e.g. if pktListDuration is 7sec and TtagTimerInterval is 5s, we
|
// e.g. if pktListDuration is 7sec and TtagTimerInterval is 5s, we
|
||||||
// skip repeat markers every pktList iteration
|
// skip repeat markers every pktList iteration
|
||||||
ttagRepeatInterval = ttagMarkers.isEmpty() ? 0 :
|
setPacketListTtagMarkers(ttagMarkers, ttagMarkers.isEmpty() ? 0 :
|
||||||
qMax(uint(kTtagTimeInterval_*1e9/(durSec*1e9+durNsec)), 1U)
|
qMax(uint(kTtagTimeInterval_*1e9
|
||||||
* totalPkts;
|
/(durSec*1e9+durNsec)),
|
||||||
if (!setPacketListTtagMarkers(ttagMarkers, ttagRepeatInterval)) {
|
1U) * totalPkts);
|
||||||
clearPacketList(); // don't leave it half baked/inconsitent
|
|
||||||
packetListAttrib.errorFlags |= FrameValueAttrib::OutOfMemoryError;
|
|
||||||
}
|
|
||||||
|
|
||||||
_out_of_memory:
|
_out_of_memory:
|
||||||
isSendQueueDirty_ = false;
|
isSendQueueDirty_ = false;
|
||||||
@ -885,9 +864,9 @@ void AbstractPort::stats(PortStats *stats)
|
|||||||
stats_.rxFrameErrors + (maxStatsValue_ - epochStats_.rxFrameErrors);
|
stats_.rxFrameErrors + (maxStatsValue_ - epochStats_.rxFrameErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamTiming::Stats AbstractPort::streamTimingStats(uint guid)
|
quint64 AbstractPort::streamTimingDelay(uint guid)
|
||||||
{
|
{
|
||||||
return streamTiming_->stats(id(), guid);
|
return streamTiming_->delay(id(), guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractPort::clearStreamTiming(uint guid)
|
void AbstractPort::clearStreamTiming(uint guid)
|
||||||
@ -900,22 +879,16 @@ void AbstractPort::streamStats(uint guid, OstProto::StreamStatsList *stats)
|
|||||||
// In case stats are being maintained elsewhere
|
// In case stats are being maintained elsewhere
|
||||||
updateStreamStats();
|
updateStreamStats();
|
||||||
|
|
||||||
// Lock for read here as updateStreamStats() above will take write lock
|
|
||||||
// and the lock is NOT recursive
|
|
||||||
QReadLocker lock(&streamStatsLock_);
|
|
||||||
|
|
||||||
if (streamStats_.contains(guid))
|
if (streamStats_.contains(guid))
|
||||||
{
|
{
|
||||||
StreamStatsTuple sst = streamStats_.value(guid);
|
StreamStatsTuple sst = streamStats_.value(guid);
|
||||||
OstProto::StreamStats *s = stats->add_stream_stats();
|
OstProto::StreamStats *s = stats->add_stream_stats();
|
||||||
StreamTiming::Stats t = streamTimingStats(guid);
|
|
||||||
|
|
||||||
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_duration(lastTransmitDuration());
|
||||||
s->set_latency(t.latency);
|
s->set_latency(streamTimingDelay(guid));
|
||||||
s->set_jitter(t.jitter);
|
|
||||||
|
|
||||||
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);
|
||||||
@ -929,10 +902,6 @@ void AbstractPort::streamStatsAll(OstProto::StreamStatsList *stats)
|
|||||||
// In case stats are being maintained elsewhere
|
// In case stats are being maintained elsewhere
|
||||||
updateStreamStats();
|
updateStreamStats();
|
||||||
|
|
||||||
// Lock for read here as updateStreamStats() above will take write lock
|
|
||||||
// and the lock is NOT recursive
|
|
||||||
QReadLocker lock(&streamStatsLock_);
|
|
||||||
|
|
||||||
// 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();
|
double txDur = lastTransmitDuration();
|
||||||
@ -942,14 +911,12 @@ void AbstractPort::streamStatsAll(OstProto::StreamStatsList *stats)
|
|||||||
i.next();
|
i.next();
|
||||||
StreamStatsTuple sst = i.value();
|
StreamStatsTuple sst = i.value();
|
||||||
OstProto::StreamStats *s = stats->add_stream_stats();
|
OstProto::StreamStats *s = stats->add_stream_stats();
|
||||||
StreamTiming::Stats t = streamTimingStats(i.key());
|
|
||||||
|
|
||||||
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_duration(txDur);
|
||||||
s->set_latency(t.latency);
|
s->set_latency(streamTimingDelay(i.key()));
|
||||||
s->set_jitter(t.jitter);
|
|
||||||
|
|
||||||
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);
|
||||||
@ -960,14 +927,12 @@ void AbstractPort::streamStatsAll(OstProto::StreamStatsList *stats)
|
|||||||
|
|
||||||
void AbstractPort::resetStreamStats(uint guid)
|
void AbstractPort::resetStreamStats(uint guid)
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&streamStatsLock_);
|
|
||||||
streamStats_.remove(guid);
|
streamStats_.remove(guid);
|
||||||
clearStreamTiming(guid);
|
clearStreamTiming(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractPort::resetStreamStatsAll()
|
void AbstractPort::resetStreamStatsAll()
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&streamStatsLock_);
|
|
||||||
streamStats_.clear();
|
streamStats_.clear();
|
||||||
clearStreamTiming();
|
clearStreamTiming();
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "../common/protocol.pb.h"
|
#include "../common/protocol.pb.h"
|
||||||
#include "streamstats.h"
|
#include "streamstats.h"
|
||||||
#include "streamtiming.h"
|
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QReadWriteLock>
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -35,6 +33,7 @@ struct InterfaceInfo;
|
|||||||
class PacketBuffer;
|
class PacketBuffer;
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
class StreamBase;
|
class StreamBase;
|
||||||
|
class StreamTiming;
|
||||||
|
|
||||||
// TODO: send notification back to client(s)
|
// TODO: send notification back to client(s)
|
||||||
#define Xnotify qWarning
|
#define Xnotify qWarning
|
||||||
@ -108,7 +107,7 @@ public:
|
|||||||
int length) = 0;
|
int length) = 0;
|
||||||
virtual void setPacketListLoopMode(bool loop,
|
virtual void setPacketListLoopMode(bool loop,
|
||||||
quint64 secDelay, quint64 nsecDelay) = 0;
|
quint64 secDelay, quint64 nsecDelay) = 0;
|
||||||
virtual bool setPacketListTtagMarkers(QList<uint> markers,
|
virtual void setPacketListTtagMarkers(QList<uint> markers,
|
||||||
uint repeatInterval) = 0;
|
uint repeatInterval) = 0;
|
||||||
int updatePacketList();
|
int updatePacketList();
|
||||||
|
|
||||||
@ -125,7 +124,7 @@ public:
|
|||||||
void stats(PortStats *stats);
|
void stats(PortStats *stats);
|
||||||
void resetStats() { epochStats_ = stats_; }
|
void resetStats() { epochStats_ = stats_; }
|
||||||
|
|
||||||
StreamTiming::Stats streamTimingStats(uint guid);
|
quint64 streamTimingDelay(uint guid);
|
||||||
void clearStreamTiming(uint guid = UINT_MAX);
|
void clearStreamTiming(uint guid = UINT_MAX);
|
||||||
|
|
||||||
// FIXME: combine single and All calls?
|
// FIXME: combine single and All calls?
|
||||||
@ -164,7 +163,6 @@ protected:
|
|||||||
quint64 maxStatsValue_;
|
quint64 maxStatsValue_;
|
||||||
struct PortStats stats_;
|
struct PortStats stats_;
|
||||||
StreamStats streamStats_;
|
StreamStats streamStats_;
|
||||||
QReadWriteLock streamStatsLock_;
|
|
||||||
//! \todo Need lock for stats access/update
|
//! \todo Need lock for stats access/update
|
||||||
|
|
||||||
const uint kTtagTimeInterval_{5}; // in seconds
|
const uint kTtagTimeInterval_{5}; // in seconds
|
||||||
|
@ -7,8 +7,6 @@ linux*:system(grep -q IFLA_STATS64 /usr/include/linux/if_link.h): \
|
|||||||
DEFINES += HAVE_IFLA_STATS64
|
DEFINES += HAVE_IFLA_STATS64
|
||||||
INCLUDEPATH += "../common"
|
INCLUDEPATH += "../common"
|
||||||
INCLUDEPATH += "../rpc"
|
INCLUDEPATH += "../rpc"
|
||||||
|
|
||||||
OBJDIR = .
|
|
||||||
win32 {
|
win32 {
|
||||||
# Support Windows Vista and above only
|
# Support Windows Vista and above only
|
||||||
DEFINES += WIN32_LEAN_AND_MEAN NTDDI_VERSION=0x06000000 _WIN32_WINNT=0x0600
|
DEFINES += WIN32_LEAN_AND_MEAN NTDDI_VERSION=0x06000000 _WIN32_WINNT=0x0600
|
||||||
@ -17,19 +15,24 @@ win32 {
|
|||||||
QMAKE_LFLAGS += -static
|
QMAKE_LFLAGS += -static
|
||||||
LIBS += -lwpcap -lpacket -liphlpapi
|
LIBS += -lwpcap -lpacket -liphlpapi
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
OBJDIR = debug
|
LIBS += -L"../common/debug" -lostproto
|
||||||
|
LIBS += -L"../rpc/debug" -lpbrpc
|
||||||
|
POST_TARGETDEPS += \
|
||||||
|
"../common/debug/libostproto.a" \
|
||||||
|
"../rpc/debug/libpbrpc.a"
|
||||||
} else {
|
} else {
|
||||||
OBJDIR = release
|
LIBS += -L"../common/release" -lostproto
|
||||||
|
LIBS += -L"../rpc/release" -lpbrpc
|
||||||
|
POST_TARGETDEPS += \
|
||||||
|
"../common/release/libostproto.a" \
|
||||||
|
"../rpc/release/libpbrpc.a"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LIBS += -lpcap
|
LIBS += -lpcap
|
||||||
|
LIBS += -L"../common" -lostproto
|
||||||
|
LIBS += -L"../rpc" -lpbrpc
|
||||||
|
POST_TARGETDEPS += "../common/libostproto.a" "../rpc/libpbrpc.a"
|
||||||
}
|
}
|
||||||
LIBS += -L"../common/$$OBJDIR" -lostproto
|
|
||||||
LIBS += -L"../rpc/$$OBJDIR" -lpbrpc
|
|
||||||
POST_TARGETDEPS += \
|
|
||||||
"../common/$$OBJDIR//libostproto.a" \
|
|
||||||
"../rpc/$$OBJDIR/libpbrpc.a"
|
|
||||||
|
|
||||||
linux {
|
linux {
|
||||||
INCLUDEPATH += "/usr/include/libnl3"
|
INCLUDEPATH += "/usr/include/libnl3"
|
||||||
LIBS += -lnl-3 -lnl-route-3
|
LIBS += -lnl-3 -lnl-route-3
|
||||||
|
@ -31,11 +31,11 @@ PcapPort::PcapPort(int id, const char *device)
|
|||||||
{
|
{
|
||||||
monitorRx_ = new PortMonitor(device, kDirectionRx, &stats_);
|
monitorRx_ = new PortMonitor(device, kDirectionRx, &stats_);
|
||||||
monitorTx_ = new PortMonitor(device, kDirectionTx, &stats_);
|
monitorTx_ = new PortMonitor(device, kDirectionTx, &stats_);
|
||||||
transmitter_ = new PcapTransmitter(device);
|
transmitter_ = new PcapTransmitter(device, streamStats_);
|
||||||
capturer_ = new PortCapturer(device);
|
capturer_ = new PortCapturer(device);
|
||||||
emulXcvr_ = new EmulationTransceiver(device, deviceManager_);
|
emulXcvr_ = new EmulationTransceiver(device, deviceManager_);
|
||||||
txTtagStatsPoller_ = new PcapTxTtagStats(device, id);
|
txTtagStatsPoller_ = new PcapTxTtagStats(device, id);
|
||||||
rxStatsPoller_ = new PcapRxStats(device, id);
|
rxStatsPoller_ = new PcapRxStats(device, streamStats_, id);
|
||||||
|
|
||||||
if (!monitorRx_->handle() || !monitorTx_->handle())
|
if (!monitorRx_->handle() || !monitorTx_->handle())
|
||||||
isUsable_ = false;
|
isUsable_ = false;
|
||||||
@ -148,14 +148,9 @@ bool PcapPort::setRateAccuracy(AbstractPort::Accuracy accuracy)
|
|||||||
|
|
||||||
void PcapPort::updateStreamStats()
|
void PcapPort::updateStreamStats()
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&streamStatsLock_);
|
// XXX: PcapTxThread already does this at the end of transmit; we
|
||||||
|
// just dump tx/rx stats poller debug stats here
|
||||||
|
|
||||||
// XXX: Transmitter may also 'adjust' rx stats in some cases (pcap
|
|
||||||
// direction not supported platforms)
|
|
||||||
transmitter_->updateTxRxStreamStats(streamStats_);
|
|
||||||
rxStatsPoller_->updateRxStreamStats(streamStats_);
|
|
||||||
|
|
||||||
// Dump tx/rx stats poller debug stats
|
|
||||||
qDebug("port %d txTtagStatsPoller: %s",
|
qDebug("port %d txTtagStatsPoller: %s",
|
||||||
id(), qUtf8Printable(txTtagStatsPoller_->debugStats()));
|
id(), qUtf8Printable(txTtagStatsPoller_->debugStats()));
|
||||||
qDebug("port %d rxStatsPoller: %s",
|
qDebug("port %d rxStatsPoller: %s",
|
||||||
@ -401,8 +396,6 @@ PcapPort::PortCapturer::PortCapturer(const char *device)
|
|||||||
|
|
||||||
PcapPort::PortCapturer::~PortCapturer()
|
PcapPort::PortCapturer::~PortCapturer()
|
||||||
{
|
{
|
||||||
if (isRunning())
|
|
||||||
stop();
|
|
||||||
capFile_.close();
|
capFile_.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,8 +544,7 @@ PcapPort::EmulationTransceiver::EmulationTransceiver(const char *device,
|
|||||||
|
|
||||||
PcapPort::EmulationTransceiver::~EmulationTransceiver()
|
PcapPort::EmulationTransceiver::~EmulationTransceiver()
|
||||||
{
|
{
|
||||||
if (isRunning())
|
stop();
|
||||||
stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapPort::EmulationTransceiver::run()
|
void PcapPort::EmulationTransceiver::run()
|
||||||
@ -741,7 +733,7 @@ void PcapPort::EmulationTransceiver::stop()
|
|||||||
QThread::msleep(10);
|
QThread::msleep(10);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qWarning("Emulation Xcvr stop requested but is not running!");
|
qWarning("Receive stop requested but is not running!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,10 @@ public:
|
|||||||
{
|
{
|
||||||
transmitter_->setPacketListLoopMode(loop, secDelay, nsecDelay);
|
transmitter_->setPacketListLoopMode(loop, secDelay, nsecDelay);
|
||||||
}
|
}
|
||||||
virtual bool setPacketListTtagMarkers(QList<uint> markers,
|
virtual void setPacketListTtagMarkers(QList<uint> markers,
|
||||||
uint repeatInterval)
|
uint repeatInterval)
|
||||||
{
|
{
|
||||||
return transmitter_->setPacketListTtagMarkers(markers, repeatInterval);
|
transmitter_->setPacketListTtagMarkers(markers, repeatInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void startTransmit() {
|
virtual void startTransmit() {
|
||||||
@ -173,8 +173,6 @@ protected:
|
|||||||
PortMonitor *monitorRx_;
|
PortMonitor *monitorRx_;
|
||||||
PortMonitor *monitorTx_;
|
PortMonitor *monitorTx_;
|
||||||
|
|
||||||
PcapRxStats *rxStatsPoller_;
|
|
||||||
|
|
||||||
void updateNotes();
|
void updateNotes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -185,6 +183,7 @@ private:
|
|||||||
PortCapturer *capturer_;
|
PortCapturer *capturer_;
|
||||||
EmulationTransceiver *emulXcvr_;
|
EmulationTransceiver *emulXcvr_;
|
||||||
PcapTxTtagStats *txTtagStatsPoller_;
|
PcapTxTtagStats *txTtagStatsPoller_;
|
||||||
|
PcapRxStats *rxStatsPoller_;
|
||||||
|
|
||||||
static pcap_if_t *deviceList_;
|
static pcap_if_t *deviceList_;
|
||||||
};
|
};
|
||||||
|
@ -22,12 +22,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "pcapextra.h"
|
#include "pcapextra.h"
|
||||||
#include "../common/debugdefs.h"
|
#include "../common/debugdefs.h"
|
||||||
#include "../common/sign.h"
|
#include "../common/sign.h"
|
||||||
#include "settings.h"
|
|
||||||
#include "streamtiming.h"
|
#include "streamtiming.h"
|
||||||
|
|
||||||
#define Xnotify qWarning // FIXME
|
#define Xnotify qWarning // FIXME
|
||||||
|
|
||||||
PcapRxStats::PcapRxStats(const char *device, int id)
|
PcapRxStats::PcapRxStats(const char *device, StreamStats &portStreamStats, int id)
|
||||||
|
: streamStats_(portStreamStats)
|
||||||
{
|
{
|
||||||
setObjectName(QString("Rx$:%1").arg(device));
|
setObjectName(QString("Rx$:%1").arg(device));
|
||||||
device_ = QString::fromLatin1(device);
|
device_ = QString::fromLatin1(device);
|
||||||
@ -57,20 +57,6 @@ void PcapRxStats::run()
|
|||||||
SignProtocol::magic(), 0, BASE_HEX);
|
SignProtocol::magic(), 0, BASE_HEX);
|
||||||
// XXX: Exclude ICMP packets which contain an embedded signed packet
|
// XXX: Exclude ICMP packets which contain an embedded signed packet
|
||||||
// For now we check upto 4 vlan tags
|
// For now we check upto 4 vlan tags
|
||||||
// XXX: libpcap for Linux has a special bpf vlan check which generates
|
|
||||||
// incorrect BPF instructions for our capture filter expression,
|
|
||||||
// so we modify it to work correctly
|
|
||||||
// See https://srivatsp.com/ostinato/ostinato-rx-stream-stats-zero/
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
capture_filter.prepend(
|
|
||||||
"not ("
|
|
||||||
"icmp or "
|
|
||||||
"(vlan and icmp) or "
|
|
||||||
"(vlan and icmp) or "
|
|
||||||
"(vlan and icmp) or "
|
|
||||||
"(vlan and icmp) "
|
|
||||||
") and ");
|
|
||||||
#else
|
|
||||||
capture_filter.append(
|
capture_filter.append(
|
||||||
"and not ("
|
"and not ("
|
||||||
"icmp or "
|
"icmp or "
|
||||||
@ -79,15 +65,8 @@ void PcapRxStats::run()
|
|||||||
"(vlan and icmp) or "
|
"(vlan and icmp) or "
|
||||||
"(vlan and icmp) "
|
"(vlan and icmp) "
|
||||||
")");
|
")");
|
||||||
#endif
|
|
||||||
|
|
||||||
// Override filter expression if one is specified in .ini
|
|
||||||
if (appSettings->contains(kInternalRxStatsFilterKey))
|
|
||||||
capture_filter = appSettings->value(kInternalRxStatsFilterKey)
|
|
||||||
.toString();
|
|
||||||
|
|
||||||
qDebug("In %s", __PRETTY_FUNCTION__);
|
qDebug("In %s", __PRETTY_FUNCTION__);
|
||||||
qDebug("RxStats Filter: %s", qPrintable(capture_filter));
|
|
||||||
|
|
||||||
handle_ = pcap_open_live(qPrintable(device_), 65535,
|
handle_ = pcap_open_live(qPrintable(device_), 65535,
|
||||||
flags, 100 /* ms */, errbuf);
|
flags, 100 /* ms */, errbuf);
|
||||||
@ -155,10 +134,14 @@ _skip_filter:
|
|||||||
&& (ttagId >> 8 != uint(portId_))) {
|
&& (ttagId >> 8 != uint(portId_))) {
|
||||||
ttagId &= 0xFF;
|
ttagId &= 0xFF;
|
||||||
timing_->recordRxTime(portId_, guid, ttagId, hdr->ts);
|
timing_->recordRxTime(portId_, guid, ttagId, hdr->ts);
|
||||||
|
timingDebug("[%d RX] %ld:%ld ttag %u guid %u", portId_,
|
||||||
|
hdr->ts.tv_sec, long(hdr->ts.tv_usec), ttagId, guid);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (SignProtocol::packetTtagId(data, hdr->caplen, &ttagId, &guid)) {
|
if (SignProtocol::packetTtagId(data, hdr->caplen, &ttagId, &guid)) {
|
||||||
timing_->recordRxTime(portId_, guid, ttagId, hdr->ts);
|
timing_->recordRxTime(portId_, guid, ttagId, hdr->ts);
|
||||||
|
timingDebug("[%d RX] %ld:%ld ttag %u guid %u", portId_,
|
||||||
|
hdr->ts.tv_sec, long(hdr->ts.tv_usec), ttagId, guid);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (guid != SignProtocol::kInvalidGuid) {
|
if (guid != SignProtocol::kInvalidGuid) {
|
||||||
@ -236,21 +219,3 @@ bool PcapRxStats::isDirectional()
|
|||||||
{
|
{
|
||||||
return isDirectional_;
|
return isDirectional_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: Stats are reset on read
|
|
||||||
void PcapRxStats::updateRxStreamStats(StreamStats &streamStats)
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&streamStatsLock_);
|
|
||||||
StreamStatsIterator i(streamStats_);
|
|
||||||
|
|
||||||
while (i.hasNext())
|
|
||||||
{
|
|
||||||
i.next();
|
|
||||||
uint guid = i.key();
|
|
||||||
StreamStatsTuple sst = i.value();
|
|
||||||
|
|
||||||
streamStats[guid].rx_pkts += sst.rx_pkts;
|
|
||||||
streamStats[guid].rx_bytes += sst.rx_bytes;
|
|
||||||
}
|
|
||||||
streamStats_.clear();
|
|
||||||
}
|
|
||||||
|
@ -24,14 +24,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "pcapsession.h"
|
#include "pcapsession.h"
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
|
|
||||||
class StreamTiming;
|
class StreamTiming;
|
||||||
|
|
||||||
class PcapRxStats: public PcapSession
|
class PcapRxStats: public PcapSession
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PcapRxStats(const char *device, int id);
|
PcapRxStats(const char *device, StreamStats &portStreamStats, int id);
|
||||||
pcap_t* handle();
|
pcap_t* handle();
|
||||||
void run();
|
void run();
|
||||||
bool start();
|
bool start();
|
||||||
@ -39,7 +37,6 @@ public:
|
|||||||
bool isRunning();
|
bool isRunning();
|
||||||
bool isDirectional();
|
bool isDirectional();
|
||||||
|
|
||||||
void updateRxStreamStats(StreamStats &streamStats); // Reset on read
|
|
||||||
private:
|
private:
|
||||||
enum State {
|
enum State {
|
||||||
kNotStarted,
|
kNotStarted,
|
||||||
@ -48,8 +45,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QString device_;
|
QString device_;
|
||||||
StreamStats streamStats_;
|
StreamStats &streamStats_;
|
||||||
QMutex streamStatsLock_;
|
|
||||||
volatile bool stop_;
|
volatile bool stop_;
|
||||||
volatile State state_;
|
volatile State state_;
|
||||||
bool isDirectional_;
|
bool isDirectional_;
|
||||||
|
@ -20,13 +20,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "pcaptransmitter.h"
|
#include "pcaptransmitter.h"
|
||||||
|
|
||||||
PcapTransmitter::PcapTransmitter(
|
PcapTransmitter::PcapTransmitter(
|
||||||
const char *device)
|
const char *device,
|
||||||
: txThread_(device)
|
StreamStats &portStreamStats)
|
||||||
|
: streamStats_(portStreamStats), txThread_(device)
|
||||||
{
|
{
|
||||||
adjustRxStreamStats_ = false;
|
adjustRxStreamStats_ = false;
|
||||||
txStats_.setObjectName(QString("TxStats:%1").arg(device));
|
txStats_.setObjectName(QString("TxStats:%1").arg(device));
|
||||||
memset(&stats_, 0, sizeof(stats_));
|
memset(&stats_, 0, sizeof(stats_));
|
||||||
txStats_.setTxThreadStats(&stats_);
|
txStats_.setTxThreadStats(&stats_);
|
||||||
|
txStats_.start(); // TODO: alongwith user transmit start
|
||||||
|
|
||||||
txThread_.setStats(&stats_);
|
txThread_.setStats(&stats_);
|
||||||
connect(&txThread_, SIGNAL(finished()), SLOT(updateTxThreadStreamStats()));
|
connect(&txThread_, SIGNAL(finished()), SLOT(updateTxThreadStreamStats()));
|
||||||
@ -34,10 +36,7 @@ PcapTransmitter::PcapTransmitter(
|
|||||||
|
|
||||||
PcapTransmitter::~PcapTransmitter()
|
PcapTransmitter::~PcapTransmitter()
|
||||||
{
|
{
|
||||||
if (txThread_.isRunning())
|
txStats_.stop(); // TODO: alongwith user transmit stop
|
||||||
txThread_.stop();
|
|
||||||
if (txStats_.isRunning())
|
|
||||||
txStats_.stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PcapTransmitter::setRateAccuracy(
|
bool PcapTransmitter::setRateAccuracy(
|
||||||
@ -56,31 +55,6 @@ bool PcapTransmitter::setStreamStatsTracking(bool enable)
|
|||||||
return txThread_.setStreamStatsTracking(enable);
|
return txThread_.setStreamStatsTracking(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: Stats are reset on read
|
|
||||||
void PcapTransmitter::updateTxRxStreamStats(StreamStats &streamStats)
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&streamStatsLock_);
|
|
||||||
StreamStatsIterator i(streamStats_);
|
|
||||||
|
|
||||||
while (i.hasNext())
|
|
||||||
{
|
|
||||||
i.next();
|
|
||||||
uint guid = i.key();
|
|
||||||
StreamStatsTuple sst = i.value();
|
|
||||||
|
|
||||||
streamStats[guid].tx_pkts += sst.tx_pkts;
|
|
||||||
streamStats[guid].tx_bytes += sst.tx_bytes;
|
|
||||||
if (adjustRxStreamStats_) {
|
|
||||||
// XXX: rx_pkts counting may lag behind tx_pkts, so stream stats
|
|
||||||
// may become negative after adjustment transiently. But this
|
|
||||||
// should fix itself once all the rx pkts come in
|
|
||||||
streamStats[guid].rx_pkts -= sst.tx_pkts;
|
|
||||||
streamStats[guid].rx_bytes -= sst.tx_bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
streamStats_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PcapTransmitter::clearPacketList()
|
void PcapTransmitter::clearPacketList()
|
||||||
{
|
{
|
||||||
txThread_.clearPacketList();
|
txThread_.clearPacketList();
|
||||||
@ -114,11 +88,11 @@ void PcapTransmitter::setPacketListLoopMode(
|
|||||||
txThread_.setPacketListLoopMode(loop, secDelay, nsecDelay);
|
txThread_.setPacketListLoopMode(loop, secDelay, nsecDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PcapTransmitter::setPacketListTtagMarkers(
|
void PcapTransmitter::setPacketListTtagMarkers(
|
||||||
QList<uint> markers,
|
QList<uint> markers,
|
||||||
uint repeatInterval)
|
uint repeatInterval)
|
||||||
{
|
{
|
||||||
return txThread_.setPacketListTtagMarkers(markers, repeatInterval);
|
txThread_.setPacketListTtagMarkers(markers, repeatInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapTransmitter::useExternalStats(AbstractPort::PortStats *stats)
|
void PcapTransmitter::useExternalStats(AbstractPort::PortStats *stats)
|
||||||
@ -128,27 +102,18 @@ void PcapTransmitter::useExternalStats(AbstractPort::PortStats *stats)
|
|||||||
|
|
||||||
void PcapTransmitter::start()
|
void PcapTransmitter::start()
|
||||||
{
|
{
|
||||||
// XXX: Start the stats thread before the tx thread, so no tx stats
|
|
||||||
// is missed
|
|
||||||
txStats_.start();
|
|
||||||
Q_ASSERT(txStats_.isRunning());
|
|
||||||
txThread_.start();
|
txThread_.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapTransmitter::stop()
|
void PcapTransmitter::stop()
|
||||||
{
|
{
|
||||||
// XXX: Stop the tx thread before the stats thread, so no tx stats
|
|
||||||
// is missed
|
|
||||||
txThread_.stop();
|
txThread_.stop();
|
||||||
Q_ASSERT(!txThread_.isRunning());
|
|
||||||
txStats_.stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PcapTransmitter::isRunning()
|
bool PcapTransmitter::isRunning()
|
||||||
{
|
{
|
||||||
return txThread_.isRunning();
|
return txThread_.isRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
double PcapTransmitter::lastTxDuration()
|
double PcapTransmitter::lastTxDuration()
|
||||||
{
|
{
|
||||||
return txThread_.lastTxDuration();
|
return txThread_.lastTxDuration();
|
||||||
@ -156,9 +121,8 @@ double PcapTransmitter::lastTxDuration()
|
|||||||
|
|
||||||
void PcapTransmitter::updateTxThreadStreamStats()
|
void PcapTransmitter::updateTxThreadStreamStats()
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&streamStatsLock_);
|
|
||||||
PcapTxThread *txThread = dynamic_cast<PcapTxThread*>(sender());
|
PcapTxThread *txThread = dynamic_cast<PcapTxThread*>(sender());
|
||||||
StreamStats threadStreamStats = txThread->streamStats();
|
const StreamStats& threadStreamStats = txThread->streamStats();
|
||||||
StreamStatsIterator i(threadStreamStats);
|
StreamStatsIterator i(threadStreamStats);
|
||||||
|
|
||||||
while (i.hasNext())
|
while (i.hasNext())
|
||||||
@ -169,5 +133,13 @@ void PcapTransmitter::updateTxThreadStreamStats()
|
|||||||
|
|
||||||
streamStats_[guid].tx_pkts += sst.tx_pkts;
|
streamStats_[guid].tx_pkts += sst.tx_pkts;
|
||||||
streamStats_[guid].tx_bytes += sst.tx_bytes;
|
streamStats_[guid].tx_bytes += sst.tx_bytes;
|
||||||
|
if (adjustRxStreamStats_) {
|
||||||
|
// XXX: rx_pkts counting may lag behind tx_pkts, so stream stats
|
||||||
|
// may become negative after adjustment transiently. But this
|
||||||
|
// should fix itself once all the rx pkts come in
|
||||||
|
streamStats_[guid].rx_pkts -= sst.tx_pkts;
|
||||||
|
streamStats_[guid].rx_bytes -= sst.tx_bytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
txThread->clearStreamStats();
|
||||||
}
|
}
|
||||||
|
@ -29,13 +29,12 @@ class PcapTransmitter : QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
PcapTransmitter(const char *device);
|
PcapTransmitter(const char *device, StreamStats &portStreamStats);
|
||||||
~PcapTransmitter();
|
~PcapTransmitter();
|
||||||
|
|
||||||
bool setRateAccuracy(AbstractPort::Accuracy accuracy);
|
bool setRateAccuracy(AbstractPort::Accuracy accuracy);
|
||||||
bool setStreamStatsTracking(bool enable);
|
bool setStreamStatsTracking(bool enable);
|
||||||
void adjustRxStreamStats(bool enable);
|
void adjustRxStreamStats(bool enable);
|
||||||
void updateTxRxStreamStats(StreamStats &streamStats); // Reset on read
|
|
||||||
|
|
||||||
void clearPacketList();
|
void clearPacketList();
|
||||||
void loopNextPacketSet(qint64 size, qint64 repeats,
|
void loopNextPacketSet(qint64 size, qint64 repeats,
|
||||||
@ -43,7 +42,7 @@ public:
|
|||||||
bool appendToPacketList(long sec, long usec, const uchar *packet,
|
bool appendToPacketList(long sec, long usec, const uchar *packet,
|
||||||
int length);
|
int length);
|
||||||
void setPacketListLoopMode(bool loop, quint64 secDelay, quint64 nsecDelay);
|
void setPacketListLoopMode(bool loop, quint64 secDelay, quint64 nsecDelay);
|
||||||
bool setPacketListTtagMarkers(QList<uint> markers, uint repeatInterval);
|
void setPacketListTtagMarkers(QList<uint> markers, uint repeatInterval);
|
||||||
|
|
||||||
void setHandle(pcap_t *handle);
|
void setHandle(pcap_t *handle);
|
||||||
void useExternalStats(AbstractPort::PortStats *stats);
|
void useExternalStats(AbstractPort::PortStats *stats);
|
||||||
@ -55,8 +54,7 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void updateTxThreadStreamStats();
|
void updateTxThreadStreamStats();
|
||||||
private:
|
private:
|
||||||
StreamStats streamStats_;
|
StreamStats &streamStats_;
|
||||||
QMutex streamStatsLock_;
|
|
||||||
PcapTxThread txThread_;
|
PcapTxThread txThread_;
|
||||||
PcapTxStats txStats_;
|
PcapTxStats txStats_;
|
||||||
StatsTuple stats_;
|
StatsTuple stats_;
|
||||||
|
@ -112,6 +112,25 @@ void PcapTxThread::clearPacketList()
|
|||||||
void PcapTxThread::loopNextPacketSet(qint64 size, qint64 repeats,
|
void PcapTxThread::loopNextPacketSet(qint64 size, qint64 repeats,
|
||||||
long repeatDelaySec, long repeatDelayNsec)
|
long repeatDelaySec, long repeatDelayNsec)
|
||||||
{
|
{
|
||||||
|
#if 0 // Don't let implicit packet sets be created
|
||||||
|
// XXX: The below change was done as part of Turbo code
|
||||||
|
// implementation alongwith calls to this function from
|
||||||
|
// AbstractPort::updatePacketListSequential(). Turbo to
|
||||||
|
// have clean code requires explicit packet sets for all
|
||||||
|
// cases (except interleaved streams). The below change
|
||||||
|
// was done so that the base code should not be affected
|
||||||
|
// after the explict packet set creation calls.
|
||||||
|
// XXX: Since we create implicit packetset for this case, skip
|
||||||
|
// This case =>
|
||||||
|
// 1. Packet set for y when x = 0
|
||||||
|
// 2. n==1 in n*x+y
|
||||||
|
// These two cases were the result of the changes in
|
||||||
|
// updatePacketListSequential() as part of Turbo changes
|
||||||
|
// mentioned above
|
||||||
|
if (repeats == 1)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
currentPacketSequence_ = new PacketSequence(trackStreamStats_);
|
currentPacketSequence_ = new PacketSequence(trackStreamStats_);
|
||||||
currentPacketSequence_->repeatCount_ = repeats;
|
currentPacketSequence_->repeatCount_ = repeats;
|
||||||
currentPacketSequence_->usecDelay_ = repeatDelaySec * long(1e6)
|
currentPacketSequence_->usecDelay_ = repeatDelaySec * long(1e6)
|
||||||
@ -202,7 +221,7 @@ void PcapTxThread::setPacketListLoopMode(
|
|||||||
loopDelay_ = secDelay*long(1e6) + nsecDelay/1000;
|
loopDelay_ = secDelay*long(1e6) + nsecDelay/1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PcapTxThread::setPacketListTtagMarkers(
|
void PcapTxThread::setPacketListTtagMarkers(
|
||||||
QList<uint> markers,
|
QList<uint> markers,
|
||||||
uint repeatInterval)
|
uint repeatInterval)
|
||||||
{
|
{
|
||||||
@ -220,7 +239,7 @@ bool PcapTxThread::setPacketListTtagMarkers(
|
|||||||
qDebug() << "FirstTtagPkt:" << firstTtagPkt_;
|
qDebug() << "FirstTtagPkt:" << firstTtagPkt_;
|
||||||
qDebug() << "TtagMarkers:" << ttagDeltaMarkers_;
|
qDebug() << "TtagMarkers:" << ttagDeltaMarkers_;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapTxThread::setHandle(pcap_t *handle)
|
void PcapTxThread::setHandle(pcap_t *handle)
|
||||||
@ -236,20 +255,14 @@ void PcapTxThread::setStats(StatsTuple *stats)
|
|||||||
stats_ = stats;
|
stats_ = stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamStats PcapTxThread::streamStats()
|
const StreamStats& PcapTxThread::streamStats()
|
||||||
{
|
{
|
||||||
// This function is typically called in client-specific-RPC-thread
|
return streamStats_;
|
||||||
// context; hence different client RPC threads may call this function,
|
}
|
||||||
// so use a lock. Although RPCs are protected by the portLock just
|
|
||||||
// for this purpose, the streamStats RPC takes a Read lock, so it can
|
|
||||||
// still happen that multiple RPC threads land up here - that's why
|
|
||||||
// this lock is required
|
|
||||||
QMutexLocker lock(&streamStatsLock_);
|
|
||||||
|
|
||||||
StreamStats ss(streamStats_); // Make a copy
|
void PcapTxThread::clearStreamStats()
|
||||||
streamStats_.clear(); // Reset on read semantics
|
{
|
||||||
|
streamStats_.clear();
|
||||||
return ss; // Return copy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapTxThread::run()
|
void PcapTxThread::run()
|
||||||
@ -290,8 +303,6 @@ void PcapTxThread::run()
|
|||||||
packetSequenceList_.at(i)->ttagL4CksumOffset_);
|
packetSequenceList_.at(i)->ttagL4CksumOffset_);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Loop:" << (returnToQIdx_ >= 0)
|
|
||||||
<< "LoopDelay:" << loopDelay_;
|
|
||||||
qDebug() << "First Ttag: " << firstTtagPkt_
|
qDebug() << "First Ttag: " << firstTtagPkt_
|
||||||
<< "Ttag Markers:" << ttagDeltaMarkers_;
|
<< "Ttag Markers:" << ttagDeltaMarkers_;
|
||||||
|
|
||||||
@ -539,8 +550,6 @@ int PcapTxThread::sendQueueTransmit(pcap_t *p, PacketSequence *seq,
|
|||||||
|
|
||||||
void PcapTxThread::updateTxStreamStats()
|
void PcapTxThread::updateTxStreamStats()
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&streamStatsLock_);
|
|
||||||
|
|
||||||
// If no packets in list, nothing to be done
|
// If no packets in list, nothing to be done
|
||||||
if (!packetListSize_)
|
if (!packetListSize_)
|
||||||
return;
|
return;
|
||||||
|
@ -24,7 +24,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "packetsequence.h"
|
#include "packetsequence.h"
|
||||||
#include "statstuple.h"
|
#include "statstuple.h"
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <pcap.h>
|
#include <pcap.h>
|
||||||
|
|
||||||
@ -43,13 +42,14 @@ public:
|
|||||||
bool appendToPacketList(long sec, long usec, const uchar *packet,
|
bool appendToPacketList(long sec, long usec, const uchar *packet,
|
||||||
int length);
|
int length);
|
||||||
void setPacketListLoopMode(bool loop, quint64 secDelay, quint64 nsecDelay);
|
void setPacketListLoopMode(bool loop, quint64 secDelay, quint64 nsecDelay);
|
||||||
bool setPacketListTtagMarkers(QList<uint> markers, uint repeatInterval);
|
void setPacketListTtagMarkers(QList<uint> markers, uint repeatInterval);
|
||||||
|
|
||||||
void setHandle(pcap_t *handle);
|
void setHandle(pcap_t *handle);
|
||||||
|
|
||||||
void setStats(StatsTuple *stats);
|
void setStats(StatsTuple *stats);
|
||||||
|
|
||||||
StreamStats streamStats(); // reset on read
|
const StreamStats& streamStats();
|
||||||
|
void clearStreamStats();
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
@ -94,7 +94,6 @@ private:
|
|||||||
StatsTuple *stats_;
|
StatsTuple *stats_;
|
||||||
StatsTuple lastStats_;
|
StatsTuple lastStats_;
|
||||||
StreamStats streamStats_;
|
StreamStats streamStats_;
|
||||||
QMutex streamStatsLock_;
|
|
||||||
quint8 ttagId_{0};
|
quint8 ttagId_{0};
|
||||||
|
|
||||||
double lastTxDuration_{0.0}; // in secs
|
double lastTxDuration_{0.0}; // in secs
|
||||||
|
@ -115,6 +115,8 @@ _skip_filter:
|
|||||||
ttagId &= 0xFF;
|
ttagId &= 0xFF;
|
||||||
#endif
|
#endif
|
||||||
timing_->recordTxTime(portId_, guid, ttagId, hdr->ts);
|
timing_->recordTxTime(portId_, guid, ttagId, hdr->ts);
|
||||||
|
timingDebug("[%d TX] %ld:%ld ttag %u guid %u", portId_,
|
||||||
|
hdr->ts.tv_sec, long(hdr->ts.tv_usec), ttagId, guid);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,4 @@ const QString kRpcServerAddress("RpcServer/Address");
|
|||||||
const QString kPortListIncludeKey("PortList/Include");
|
const QString kPortListIncludeKey("PortList/Include");
|
||||||
const QString kPortListExcludeKey("PortList/Exclude");
|
const QString kPortListExcludeKey("PortList/Exclude");
|
||||||
|
|
||||||
//
|
|
||||||
// Internal Section Keys
|
|
||||||
//
|
|
||||||
const QString kInternalRxStatsFilterKey("Internal/RxStatsFilter");
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "streamtiming.h"
|
#include "streamtiming.h"
|
||||||
|
|
||||||
|
#include "../common/debugdefs.h"
|
||||||
#include "timestamp.h"
|
#include "timestamp.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@ -62,10 +63,52 @@ void StreamTiming::stop(uint portId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamTiming::Stats StreamTiming::stats(uint portId, uint guid)
|
bool StreamTiming::recordTxTime(uint portId, uint guid, uint ttagId,
|
||||||
|
const struct timespec ×tamp)
|
||||||
{
|
{
|
||||||
Stats stats = {0, 0};
|
TxRxKey key = makeKey(guid, ttagId);
|
||||||
|
TtagData value = { .timeStamp = timestamp, .portId = portId};
|
||||||
|
|
||||||
|
QMutexLocker locker(&txHashLock_);
|
||||||
|
txHash_.insert(key, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StreamTiming::recordRxTime(uint portId, uint guid, uint ttagId,
|
||||||
|
const struct timespec ×tamp)
|
||||||
|
{
|
||||||
|
TxRxKey key = makeKey(guid, ttagId);
|
||||||
|
TtagData value = { .timeStamp = timestamp, .portId = portId};
|
||||||
|
|
||||||
|
QMutexLocker locker(&rxHashLock_);
|
||||||
|
rxHash_.insert(key, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StreamTiming::recordTxTime(uint portId, uint guid, uint ttagId,
|
||||||
|
const struct timeval ×tamp)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = timestamp.tv_sec;
|
||||||
|
ts.tv_nsec = timestamp.tv_usec*1000;
|
||||||
|
|
||||||
|
return recordTxTime(portId, guid, ttagId, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StreamTiming::recordRxTime(uint portId, uint guid, uint ttagId,
|
||||||
|
const struct timeval ×tamp)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = timestamp.tv_sec;
|
||||||
|
ts.tv_nsec = timestamp.tv_usec*1000;
|
||||||
|
|
||||||
|
return recordRxTime(portId, guid, ttagId, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 StreamTiming::delay(uint portId, uint guid)
|
||||||
|
{
|
||||||
Q_ASSERT(guid <= SignProtocol::kMaxGuid);
|
Q_ASSERT(guid <= SignProtocol::kMaxGuid);
|
||||||
|
|
||||||
// Process anything pending first
|
// Process anything pending first
|
||||||
@ -74,17 +117,13 @@ StreamTiming::Stats StreamTiming::stats(uint portId, uint guid)
|
|||||||
QMutexLocker locker(&timingLock_);
|
QMutexLocker locker(&timingLock_);
|
||||||
|
|
||||||
if (!timing_.contains(portId))
|
if (!timing_.contains(portId))
|
||||||
return stats;
|
return 0;
|
||||||
|
|
||||||
Timing t = timing_.value(portId)->value(guid);
|
Timing t = timing_.value(portId)->value(guid);
|
||||||
if (t.countDelays == 0)
|
if (t.countDelays == 0)
|
||||||
return stats;
|
return 0;
|
||||||
|
|
||||||
stats.latency = timespecToNsecs(t.sumDelays)/t.countDelays;
|
return timespecToNsecs(t.sumDelays)/t.countDelays;
|
||||||
if (t.countDelays > 1)
|
|
||||||
stats.jitter = t.sumJitter/(t.countDelays-1);
|
|
||||||
|
|
||||||
return stats;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamTiming::clear(uint portId, uint guid)
|
void StreamTiming::clear(uint portId, uint guid)
|
||||||
@ -101,7 +140,7 @@ void StreamTiming::clear(uint portId, uint guid)
|
|||||||
if (!portTiming)
|
if (!portTiming)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (guid >= SignProtocol::kInvalidGuid)
|
if (guid == SignProtocol::kInvalidGuid)
|
||||||
portTiming->clear(); // remove ALL guids
|
portTiming->clear(); // remove ALL guids
|
||||||
else
|
else
|
||||||
portTiming->remove(guid);
|
portTiming->remove(guid);
|
||||||
@ -125,7 +164,7 @@ int StreamTiming::processRecords()
|
|||||||
struct timespec diff;
|
struct timespec diff;
|
||||||
timespecsub(&rxTime, &txTime, &diff);
|
timespecsub(&rxTime, &txTime, &diff);
|
||||||
|
|
||||||
uint guid = guidFromKey(i.key());
|
uint guid = i.key() >> 8;
|
||||||
uint portId = i.value().portId;
|
uint portId = i.value().portId;
|
||||||
|
|
||||||
if (!timing_.contains(portId))
|
if (!timing_.contains(portId))
|
||||||
@ -133,25 +172,19 @@ int StreamTiming::processRecords()
|
|||||||
PortTiming *portTiming = timing_.value(portId);
|
PortTiming *portTiming = timing_.value(portId);
|
||||||
Timing &guidTiming = (*portTiming)[guid];
|
Timing &guidTiming = (*portTiming)[guid];
|
||||||
timespecadd(&guidTiming.sumDelays, &diff, &guidTiming.sumDelays);
|
timespecadd(&guidTiming.sumDelays, &diff, &guidTiming.sumDelays);
|
||||||
if (guidTiming.countDelays)
|
|
||||||
guidTiming.sumJitter += abs(
|
|
||||||
diff.tv_sec*long(1e9) + diff.tv_nsec
|
|
||||||
- guidTiming.lastDelay.tv_sec*long(1e9)
|
|
||||||
- guidTiming.lastDelay.tv_nsec);
|
|
||||||
guidTiming.lastDelay = diff;
|
|
||||||
guidTiming.countDelays++;
|
guidTiming.countDelays++;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
timingDebug("[%u/%u/%u] diff %ld.%09ld (%ld.%09ld - %ld.%09ld)",
|
timingDebug("[%u/%u/%u] diff %ld.%09ld (%ld.%09ld - %ld.%09ld)",
|
||||||
i.value().portId, guid, ttagIdFromKey(i.key()),
|
i.value().portId, guid, i.key() & 0xFF,
|
||||||
diff.tv_sec, diff.tv_nsec,
|
diff.tv_sec, diff.tv_nsec,
|
||||||
rxTime.tv_sec, rxTime.tv_nsec,
|
rxTime.tv_sec, rxTime.tv_nsec,
|
||||||
txTime.tv_sec, txTime.tv_nsec);
|
txTime.tv_sec, txTime.tv_nsec);
|
||||||
timingDebug("[%u/%u](%d) total %ld.%09ld count %u jittersum %09llu",
|
timingDebug("%d:[%u/%u] total %ld.%09ld count %u",
|
||||||
i.value().portId, guid, count,
|
count, i.value().portId, guid,
|
||||||
guidTiming.sumDelays.tv_sec, guidTiming.sumDelays.tv_nsec,
|
guidTiming.sumDelays.tv_sec, guidTiming.sumDelays.tv_nsec,
|
||||||
guidTiming.countDelays, guidTiming.sumJitter);
|
guidTiming.countDelays);
|
||||||
}
|
}
|
||||||
i = rxHash_.erase(i);
|
i = rxHash_.erase(i);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#ifndef _STREAM_TIMING
|
#ifndef _STREAM_TIMING
|
||||||
#define _STREAM_TIMING
|
#define _STREAM_TIMING
|
||||||
|
|
||||||
#include "../common/debugdefs.h"
|
|
||||||
#include "../common/sign.h"
|
#include "../common/sign.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
@ -34,12 +33,6 @@ class StreamTiming : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
struct Stats
|
|
||||||
{
|
|
||||||
quint64 latency;
|
|
||||||
quint64 jitter;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool recordTxTime(uint portId, uint guid, uint ttagId,
|
bool recordTxTime(uint portId, uint guid, uint ttagId,
|
||||||
const struct timespec ×tamp);
|
const struct timespec ×tamp);
|
||||||
bool recordRxTime(uint portId, uint guid, uint ttagId,
|
bool recordRxTime(uint portId, uint guid, uint ttagId,
|
||||||
@ -50,10 +43,7 @@ public:
|
|||||||
bool recordRxTime(uint portId, uint guid, uint ttagId,
|
bool recordRxTime(uint portId, uint guid, uint ttagId,
|
||||||
const struct timeval ×tamp);
|
const struct timeval ×tamp);
|
||||||
|
|
||||||
bool recordTxTime(uint portId, uint *ttagList, int count,
|
quint64 delay(uint portId, uint guid);
|
||||||
const struct timespec ×tamp);
|
|
||||||
|
|
||||||
Stats stats(uint portId, uint guid);
|
|
||||||
void clear(uint portId, uint guid = SignProtocol::kInvalidGuid);
|
void clear(uint portId, uint guid = SignProtocol::kInvalidGuid);
|
||||||
|
|
||||||
static StreamTiming* instance();
|
static StreamTiming* instance();
|
||||||
@ -68,6 +58,10 @@ private:
|
|||||||
int processRecords();
|
int processRecords();
|
||||||
int deleteStaleRecords();
|
int deleteStaleRecords();
|
||||||
|
|
||||||
|
quint32 makeKey(uint guid, uint ttagId) {
|
||||||
|
return guid << 8 | (ttagId & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
// XXX: use only time intervals, not absolute time
|
// XXX: use only time intervals, not absolute time
|
||||||
quint64 timespecToNsecs(const struct timespec &interval) {
|
quint64 timespecToNsecs(const struct timespec &interval) {
|
||||||
return interval.tv_nsec + interval.tv_sec*1e9;
|
return interval.tv_nsec + interval.tv_sec*1e9;
|
||||||
@ -78,38 +72,23 @@ private:
|
|||||||
uint portId;
|
uint portId;
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX: used only as a Qt Container value, so members will get init to 0
|
|
||||||
// when this struct is retrieved from the container due to Qt's default-
|
|
||||||
// cosntructed value semantics
|
|
||||||
struct Timing {
|
struct Timing {
|
||||||
struct timespec sumDelays; // nanosec resolution
|
struct timespec sumDelays; // nanosec resolution
|
||||||
struct timespec lastDelay;
|
|
||||||
quint64 sumJitter; // nanosec resolution
|
|
||||||
uint countDelays;
|
uint countDelays;
|
||||||
};
|
};
|
||||||
|
|
||||||
QSet<uint> activePortSet_;
|
QSet<uint> activePortSet_;
|
||||||
|
|
||||||
// XXX: TxRxKey = ttagid (8 bit MSB) + guid (24 bit LSB)
|
// XXX: TxRxKey = guid (24 bit MSB) + ttagid (8 bit LSB)
|
||||||
// TODO: encode tx port in packet and use as part of key
|
// TODO: encode tx port in in packet and use as part of key
|
||||||
typedef quint32 TxRxKey;
|
typedef quint32 TxRxKey;
|
||||||
TxRxKey makeKey(uint guid, uint ttagId) {
|
|
||||||
return (ttagId << 24 ) | (guid & 0x00FFFFFF);
|
|
||||||
}
|
|
||||||
uint guidFromKey(TxRxKey key) {
|
|
||||||
return uint(key) & 0x00FFFFFF;
|
|
||||||
}
|
|
||||||
uint ttagIdFromKey(TxRxKey key) {
|
|
||||||
return uint(key) >> 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<TxRxKey, TtagData> txHash_;
|
QHash<TxRxKey, TtagData> txHash_;
|
||||||
QHash<TxRxKey, TtagData> rxHash_;
|
QHash<TxRxKey, TtagData> rxHash_;
|
||||||
QMutex txHashLock_;
|
QMutex txHashLock_;
|
||||||
QMutex rxHashLock_;
|
QMutex rxHashLock_;
|
||||||
|
|
||||||
typedef uint PortIdKey;
|
typedef uint PortIdKey;
|
||||||
typedef uint GuidKey; // guid only, no ttagid
|
typedef uint GuidKey;
|
||||||
typedef QHash<GuidKey, Timing> PortTiming;
|
typedef QHash<GuidKey, Timing> PortTiming;
|
||||||
QHash<PortIdKey, PortTiming*> timing_;
|
QHash<PortIdKey, PortTiming*> timing_;
|
||||||
QMutex timingLock_;
|
QMutex timingLock_;
|
||||||
@ -118,79 +97,4 @@ private:
|
|||||||
QTimer *gcTimer_; // Garbage collection for stale tx records
|
QTimer *gcTimer_; // Garbage collection for stale tx records
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
|
||||||
bool StreamTiming::recordTxTime(uint portId, uint guid, uint ttagId,
|
|
||||||
const struct timespec ×tamp)
|
|
||||||
{
|
|
||||||
TxRxKey key = makeKey(guid, ttagId);
|
|
||||||
TtagData value = { .timeStamp = timestamp, .portId = portId};
|
|
||||||
|
|
||||||
timingDebug("[%d TX] %ld:%ld ttag %u guid %u", portId,
|
|
||||||
timestamp.tv_sec, long(timestamp.tv_nsec), ttagId, guid);
|
|
||||||
|
|
||||||
QMutexLocker locker(&txHashLock_);
|
|
||||||
txHash_.insert(key, value);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
bool StreamTiming::recordRxTime(uint portId, uint guid, uint ttagId,
|
|
||||||
const struct timespec ×tamp)
|
|
||||||
{
|
|
||||||
TxRxKey key = makeKey(guid, ttagId);
|
|
||||||
TtagData value = { .timeStamp = timestamp, .portId = portId};
|
|
||||||
|
|
||||||
timingDebug("[%d RX] %ld:%ld ttag %u guid %u", portId,
|
|
||||||
timestamp.tv_sec, long(timestamp.tv_nsec), ttagId, guid);
|
|
||||||
|
|
||||||
QMutexLocker locker(&rxHashLock_);
|
|
||||||
rxHash_.insert(key, value);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
bool StreamTiming::recordTxTime(uint portId, uint guid, uint ttagId,
|
|
||||||
const struct timeval ×tamp)
|
|
||||||
{
|
|
||||||
struct timespec ts;
|
|
||||||
ts.tv_sec = timestamp.tv_sec;
|
|
||||||
ts.tv_nsec = timestamp.tv_usec*1000;
|
|
||||||
|
|
||||||
return recordTxTime(portId, guid, ttagId, ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
bool StreamTiming::recordRxTime(uint portId, uint guid, uint ttagId,
|
|
||||||
const struct timeval ×tamp)
|
|
||||||
{
|
|
||||||
struct timespec ts;
|
|
||||||
ts.tv_sec = timestamp.tv_sec;
|
|
||||||
ts.tv_nsec = timestamp.tv_usec*1000;
|
|
||||||
|
|
||||||
return recordRxTime(portId, guid, ttagId, ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TTagList contains 32-bit ttags formatted as ttagId (8msb) + guid (24lsb)
|
|
||||||
inline
|
|
||||||
bool StreamTiming::recordTxTime(uint portId, uint *ttagList, int count,
|
|
||||||
const struct timespec ×tamp)
|
|
||||||
{
|
|
||||||
TtagData value = { .timeStamp = timestamp, .portId = portId};
|
|
||||||
QMutexLocker locker(&txHashLock_);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
TxRxKey key = TxRxKey(ttagList[i]);
|
|
||||||
|
|
||||||
timingDebug("[%d TX] %ld:%ld ttag %u guid %u", portId,
|
|
||||||
timestamp.tv_sec, long(timestamp.tv_nsec),
|
|
||||||
ttagIdFromKey(key), guidFromKey(key));
|
|
||||||
|
|
||||||
txHash_.insert(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,26 +1,33 @@
|
|||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
CONFIG += qt console
|
CONFIG += qt console
|
||||||
QT += xml network script
|
QT += xml network script widgets
|
||||||
INCLUDEPATH += "../rpc/" "../common/" "../client"
|
INCLUDEPATH += "../rpc/" "../common/" "../client"
|
||||||
|
|
||||||
OBJDIR = .
|
|
||||||
win32 {
|
win32 {
|
||||||
LIBS += -lwpcap -lpacket
|
LIBS += -lwpcap -lpacket
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
OBJDIR = debug
|
LIBS += -L"../common/debug" -lostprotogui -lostproto
|
||||||
|
LIBS += -L"../rpc/debug" -lpbrpc
|
||||||
|
POST_TARGETDEPS += \
|
||||||
|
"../common/debug/libostprotogui.a" \
|
||||||
|
"../common/debug/libostproto.a" \
|
||||||
|
"../rpc/debug/libpbrpc.a"
|
||||||
} else {
|
} else {
|
||||||
OBJDIR = release
|
LIBS += -L"../common/release" -lostprotogui -lostproto
|
||||||
|
LIBS += -L"../rpc/release" -lpbrpc
|
||||||
|
POST_TARGETDEPS += \
|
||||||
|
"../common/release/libostprotogui.a" \
|
||||||
|
"../common/release/libostproto.a" \
|
||||||
|
"../rpc/release/libpbrpc.a"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LIBS += -lpcap
|
LIBS += -lpcap
|
||||||
|
LIBS += -L"../common" -lostprotogui -lostproto
|
||||||
|
LIBS += -L"../rpc" -lpbrpc
|
||||||
|
POST_TARGETDEPS += \
|
||||||
|
"../common/libostprotogui.a" \
|
||||||
|
"../common/libostproto.a" \
|
||||||
|
"../rpc/libpbrpc.a"
|
||||||
}
|
}
|
||||||
LIBS += -L"../common/$$OBJDIR" -lostfile -lostproto
|
|
||||||
LIBS += -L"../rpc/$$OBJDIR" -lpbrpc
|
|
||||||
POST_TARGETDEPS += \
|
|
||||||
"../common/$$OBJDIR/libostfile.a" \
|
|
||||||
"../common/$$OBJDIR/libostproto.a" \
|
|
||||||
"../rpc/$$OBJDIR/libpbrpc.a"
|
|
||||||
|
|
||||||
LIBS += -lprotobuf
|
LIBS += -lprotobuf
|
||||||
LIBS += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
|
LIBS += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
APP_VERSION = 1.4.0-dev
|
APP_VERSION = 1.3.0-dev
|
||||||
APP_REVISION = $(shell git rev-parse --short=12 --verify HEAD)
|
APP_REVISION = $(shell git rev-parse --short=12 --verify HEAD)
|
||||||
#uncomment the below line in a source package and fill-in the correct revision
|
#uncomment the below line in a source package and fill-in the correct revision
|
||||||
#APP_REVISION = <rev-hash>@
|
#APP_REVISION = <rev-hash>@
|
||||||
|
Loading…
Reference in New Issue
Block a user