- Packet Transmission is now a separate thread to allow for event processing
- Packet Transmission rate (IPG) is done - need to test. IBG is still pending - Per port there are two pcap_t handles - one for Rx and one for Tx: since PCAP does not capture loopback packets, transmission by OST happens on Rx Hdl so that they are recieved on the Tx Hdl - pcap_loop() changed to pcap_dispatch() to be able to work in PCAP/Linux - forgot exactly why :-) - Removed NIC stats - Implemented PortStatsFilterDialog ordering of ports - PortStatsWindow - Tooltip on Port column dispays stats limitations
This commit is contained in:
parent
0c70668e56
commit
017cb75ae5
@ -6,7 +6,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>588</width>
|
||||
<height>298</height>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
@ -17,9 +17,21 @@
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QListView" name="lvUnselected" >
|
||||
<property name="acceptDrops" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragEnabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropMode" >
|
||||
<enum>QAbstractItemView::NoDragDrop</enum>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="movement" >
|
||||
<enum>QListView::Static</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -68,6 +80,18 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="lvSelected" >
|
||||
<property name="acceptDrops" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragEnabled" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropOverwriteMode" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropMode" >
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
@ -76,50 +100,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton" >
|
||||
<property name="text" >
|
||||
<string>U</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton_2" >
|
||||
<property name="text" >
|
||||
<string>D</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -4,13 +4,6 @@ PortStatsFilterDialog::PortStatsFilterDialog(QWidget *parent)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
// TODO(MED): Use ExtendedSelection and use "selected" instead of
|
||||
// "current" for selecting in/out
|
||||
// TODO(MED): Ensure items are READ-ONLY not editable
|
||||
// TODO(MED): Enable "double-click" on items
|
||||
lvUnselected->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
lvSelected->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
mUnselected.setSortRole(PositionRole);
|
||||
|
||||
lvUnselected->setModel(&mUnselected);
|
||||
@ -37,6 +30,10 @@ QList<uint> PortStatsFilterDialog::getItemList(bool* ok,
|
||||
|
||||
item = new QStandardItem(model->headerData(i, orientation).toString());
|
||||
item->setData(i, PositionRole);
|
||||
item->setFlags(Qt::ItemIsSelectable
|
||||
| Qt::ItemIsDragEnabled
|
||||
//| Qt::ItemIsDropEnabled
|
||||
| Qt::ItemIsEnabled);
|
||||
|
||||
if (initial.contains(i))
|
||||
mSelected.appendRow(item);
|
||||
@ -62,6 +59,36 @@ QList<uint> PortStatsFilterDialog::getItemList(bool* ok,
|
||||
}
|
||||
|
||||
void PortStatsFilterDialog::on_tbSelectIn_clicked()
|
||||
{
|
||||
QStandardItem *item;
|
||||
while (lvUnselected->selectionModel()->selectedIndexes().size())
|
||||
{
|
||||
item = mUnselected.takeItem(lvUnselected->selectionModel()->
|
||||
selectedIndexes().at(0).row());
|
||||
if (mUnselected.removeRow(lvUnselected->selectionModel()->
|
||||
selectedIndexes().at(0).row()))
|
||||
mSelected.appendRow(item);
|
||||
}
|
||||
}
|
||||
|
||||
void PortStatsFilterDialog::on_tbSelectOut_clicked()
|
||||
{
|
||||
QStandardItem *item;
|
||||
|
||||
while (lvSelected->selectionModel()->selectedIndexes().size())
|
||||
{
|
||||
item = mSelected.takeItem(lvSelected->selectionModel()->
|
||||
selectedIndexes().at(0).row());
|
||||
if (mSelected.removeRow(lvSelected->selectionModel()->
|
||||
selectedIndexes().at(0).row()))
|
||||
{
|
||||
mUnselected.appendRow(item);
|
||||
mUnselected.sort(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PortStatsFilterDialog::on_lvUnselected_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
QStandardItem *item;
|
||||
|
||||
@ -70,7 +97,7 @@ void PortStatsFilterDialog::on_tbSelectIn_clicked()
|
||||
mSelected.appendRow(item);
|
||||
}
|
||||
|
||||
void PortStatsFilterDialog::on_tbSelectOut_clicked()
|
||||
void PortStatsFilterDialog::on_lvSelected_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
QStandardItem *item;
|
||||
|
||||
|
@ -27,6 +27,8 @@ private:
|
||||
private slots:
|
||||
void on_tbSelectIn_clicked();
|
||||
void on_tbSelectOut_clicked();
|
||||
void on_lvUnselected_doubleClicked(const QModelIndex &index);
|
||||
void on_lvSelected_doubleClicked(const QModelIndex &index);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -105,12 +105,6 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
||||
case e_STAT_FRAME_RECV_RATE:
|
||||
return stats.rx_pps();
|
||||
|
||||
case e_STAT_FRAMES_RCVD_NIC:
|
||||
return stats.rx_pkts_nic();
|
||||
|
||||
case e_STAT_FRAMES_SENT_NIC:
|
||||
return stats.tx_pkts_nic();
|
||||
|
||||
case e_STAT_BYTES_RCVD:
|
||||
return stats.rx_bytes();
|
||||
|
||||
@ -123,12 +117,19 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
||||
case e_STAT_BYTE_RECV_RATE:
|
||||
return stats.rx_bps();
|
||||
|
||||
#if 0
|
||||
case e_STAT_FRAMES_RCVD_NIC:
|
||||
return stats.rx_pkts_nic();
|
||||
|
||||
case e_STAT_FRAMES_SENT_NIC:
|
||||
return stats.tx_pkts_nic();
|
||||
|
||||
case e_STAT_BYTES_RCVD_NIC:
|
||||
return stats.rx_bytes_nic();
|
||||
|
||||
case e_STAT_BYTES_SENT_NIC:
|
||||
return stats.tx_bytes_nic();
|
||||
|
||||
#endif
|
||||
default:
|
||||
qWarning("%s: Unhandled stats id %d\n", __FUNCTION__,
|
||||
index.row());
|
||||
@ -142,11 +143,39 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
#ifdef Q_OS_WIN32
|
||||
// TODO(MED): The limitations should be the server's not the client's!
|
||||
// Ideally we shd enhance the protocol to convey limitation(s), if any,
|
||||
// from server to client
|
||||
if (role == Qt::ToolTipRole)
|
||||
{
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
return QString("<b>Limitation(s)</b>"
|
||||
"<p><i>Frames/Bytes Receieved</i>: Includes non Ostinato Tx pkts also (Tx by Ostinato are not included)<br>"
|
||||
"<i>Frames/Bytes Sent</i>: Only Ostinato Tx pkts (Tx by others NOT included)</p>"
|
||||
"<p>Rx/Tx Rates are derived from the above and hence subject to same limitations</p>"
|
||||
);
|
||||
}
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal)
|
||||
return QString("Port %1").arg(section);
|
||||
{
|
||||
uint portGroupIdx, portIdx;
|
||||
|
||||
getDomainIndexes(index(0, section), portGroupIdx, portIdx);
|
||||
#ifdef Q_OS_WIN32
|
||||
return QString("Port %1/%2 (*)").arg(portGroupIdx).arg(portIdx);
|
||||
#else
|
||||
return QString("Port %1/%2").arg(portGroupIdx).arg(portIdx);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return PortStatName.at(section);
|
||||
}
|
||||
@ -212,7 +241,6 @@ void PortStatsModel::when_portListChanged()
|
||||
|
||||
void PortStatsModel::on_portStatsUpdate(int port, void*stats)
|
||||
{
|
||||
// FIXME(MED): update only the changed port not all
|
||||
QModelIndex topLeft = index(port, 0, QModelIndex());
|
||||
QModelIndex bottomRight = index(port, e_STAT_MAX, QModelIndex());
|
||||
|
||||
|
@ -9,14 +9,16 @@ typedef enum {
|
||||
e_STAT_FRAMES_SENT,
|
||||
e_STAT_FRAME_SEND_RATE,
|
||||
e_STAT_FRAME_RECV_RATE,
|
||||
e_STAT_FRAMES_RCVD_NIC,
|
||||
e_STAT_FRAMES_SENT_NIC,
|
||||
e_STAT_BYTES_RCVD,
|
||||
e_STAT_BYTES_SENT,
|
||||
e_STAT_BYTE_SEND_RATE,
|
||||
e_STAT_BYTE_RECV_RATE,
|
||||
#if 0
|
||||
e_STAT_FRAMES_RCVD_NIC,
|
||||
e_STAT_FRAMES_SENT_NIC,
|
||||
e_STAT_BYTES_RCVD_NIC,
|
||||
e_STAT_BYTES_SENT_NIC,
|
||||
#endif
|
||||
e_STAT_MAX
|
||||
} PortStat;
|
||||
|
||||
@ -25,14 +27,16 @@ static QStringList PortStatName = (QStringList()
|
||||
<< "Frames Sent"
|
||||
<< "Frame Send Rate (fps)"
|
||||
<< "Frame Receive Rate (fps)"
|
||||
<< "Frames Received (NIC)"
|
||||
<< "Frames Sent (NIC)"
|
||||
<< "Bytes Received"
|
||||
<< "Bytes Sent"
|
||||
<< "Byte Send Rate (Bps)"
|
||||
<< "Byte Receive Rate (Bps)"
|
||||
#if 0
|
||||
<< "Frames Received (NIC)"
|
||||
<< "Frames Sent (NIC)"
|
||||
<< "Bytes Received (NIC)"
|
||||
<< "Bytes Sent (NIC)"
|
||||
#endif
|
||||
);
|
||||
|
||||
class PortGroupList;
|
||||
|
@ -13,11 +13,11 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
|
||||
this->pgl = pgl;
|
||||
model = pgl->getPortStatsModel();
|
||||
tvPortStats->setModel(model);
|
||||
tvPortStats->horizontalHeader()->setMovable(true);
|
||||
|
||||
tvPortStats->verticalHeader()->setHighlightSections(false);
|
||||
tvPortStats->verticalHeader()->setDefaultSectionSize(
|
||||
tvPortStats->verticalHeader()->minimumSectionSize());
|
||||
|
||||
}
|
||||
|
||||
PortStatsWindow::~PortStatsWindow()
|
||||
@ -109,7 +109,17 @@ void PortStatsWindow::on_tbFilter_clicked()
|
||||
|
||||
newColumns = dialog.getItemList(&ok, model, Qt::Horizontal, currentColumns);
|
||||
|
||||
if(ok)
|
||||
if (ok)
|
||||
{
|
||||
// hide/show sections first ...
|
||||
for(int i = 0; i < model->columnCount(); i++)
|
||||
tvPortStats->setColumnHidden(i, !newColumns.contains(i));
|
||||
|
||||
// ... then for the 'shown' columns, set the visual index
|
||||
for(int i = 0; i < newColumns.size(); i++)
|
||||
{
|
||||
tvPortStats->horizontalHeader()->moveSection(tvPortStats->
|
||||
horizontalHeader()->visualIndex(newColumns.at(i)), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,6 @@
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QFrame" name="frame" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
</property>
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
@ -28,7 +25,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbStartTransmit" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
<string>Start Tx</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Starts transmit on selected port(s)</string>
|
||||
@ -44,7 +41,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbStopTransmit" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
<string>Stop Tx</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Stops transmit on selected port(s)</string>
|
||||
@ -60,7 +57,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbClear" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
<string>Clear Selected Port Stats</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Clears statistics of the selected port(s)</string>
|
||||
@ -73,7 +70,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbClearAll" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
<string>Clear All Ports Stats</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Clears statistics of all ports</string>
|
||||
@ -86,7 +83,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbStartCapture" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
<string>Start Capture</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Captures packets on the selected port(s)</string>
|
||||
@ -102,7 +99,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbStopCapture" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
<string>Stop Capture</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>End capture on selecteed port(s)</string>
|
||||
@ -118,7 +115,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbViewCapture" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
<string>View Capture Buffer</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>View captured packets on selected port(s)</string>
|
||||
@ -133,9 +130,6 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
@ -143,9 +137,6 @@
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
@ -159,9 +150,6 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbFilter" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
</property>
|
||||
<property name="statusTip" >
|
||||
<string>Select which ports to view</string>
|
||||
</property>
|
||||
@ -177,11 +165,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tvPortStats" >
|
||||
<property name="toolTip" >
|
||||
<string>Clear All</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTableView" name="tvPortStats" />
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <qglobal.h>
|
||||
#include <qendian.h>
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#if 0
|
||||
#include <pcap-int.h>
|
||||
#include <Ntddndis.h>
|
||||
#endif
|
||||
@ -482,7 +482,7 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
|
||||
// ------------------ PortInfo --------------------
|
||||
//
|
||||
PortInfo::PortInfo(uint id, pcap_if_t *dev)
|
||||
: monitorRx(this), monitorTx(this)
|
||||
: monitorRx(this), monitorTx(this), transmitter(this)
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
|
||||
@ -501,10 +501,12 @@ PortInfo::PortInfo(uint id, pcap_if_t *dev)
|
||||
dev->name, pcap_geterr(devHandleRx));
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (pcap_setdirection(devHandleRx, PCAP_D_IN)<0)
|
||||
{
|
||||
qDebug("[%s] Error setting direction inbound only\n", dev->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* By default, put the interface in statistics mode */
|
||||
if (pcap_setmode(devHandleRx, MODE_STAT)<0)
|
||||
@ -520,10 +522,12 @@ PortInfo::PortInfo(uint id, pcap_if_t *dev)
|
||||
dev->name, pcap_geterr(devHandleTx));
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (pcap_setdirection(devHandleTx, PCAP_D_OUT)<0)
|
||||
{
|
||||
qDebug("[%s] Error setting direction outbound only\n", dev->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* By default, put the interface in statistics mode */
|
||||
if (pcap_setmode(devHandleTx, MODE_STAT)<0)
|
||||
@ -534,14 +538,15 @@ PortInfo::PortInfo(uint id, pcap_if_t *dev)
|
||||
d.mutable_port_id()->set_id(id);
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
d.set_name(QString("if%1").arg(id).toAscii().constData());
|
||||
d.set_name(QString("if%1 ").arg(id).toAscii().constData());
|
||||
#else
|
||||
if (dev->name)
|
||||
d.set_name(dev->name);
|
||||
else
|
||||
d.set_name(QString("if%1").arg(id).toAscii().constData());
|
||||
d.set_name(QString("if%1 ").arg(id).toAscii().constData());
|
||||
#endif
|
||||
d.set_name(d.name()+pcap_datalink_val_to_name(pcap_datalink(devHandleRx)));
|
||||
d.set_name(d.name()+"{"+
|
||||
pcap_datalink_val_to_name(pcap_datalink(devHandleRx))+"}");
|
||||
|
||||
if (dev->description)
|
||||
d.set_description(dev->description);
|
||||
@ -586,6 +591,7 @@ void PortInfo::update()
|
||||
if (streamList[i].d.core().is_enabled())
|
||||
{
|
||||
int numPackets, numBursts;
|
||||
long ipg;
|
||||
|
||||
switch (streamList[i].d.control().unit())
|
||||
{
|
||||
@ -596,6 +602,8 @@ void PortInfo::update()
|
||||
case OstProto::StreamControl::e_su_packets:
|
||||
numBursts = 1;
|
||||
numPackets = streamList[i].d.control().num_packets();
|
||||
ipg = 1000000/streamList[i].d.control().packets_per_sec();
|
||||
qDebug("ipg = %ld\n", ipg);
|
||||
break;
|
||||
default:
|
||||
qWarning("Unhandled stream control unit %d",
|
||||
@ -603,9 +611,11 @@ void PortInfo::update()
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
pktHdr.ts.tv_sec = 0;
|
||||
pktHdr.ts.tv_usec = 0;
|
||||
for (int j = 0; j < numBursts; j++)
|
||||
{
|
||||
// FIXME(HI): IBG rate (bursts_per_sec)
|
||||
for (int k = 0; k < numPackets; k++)
|
||||
{
|
||||
int len;
|
||||
@ -615,7 +625,12 @@ void PortInfo::update()
|
||||
if (len > 0)
|
||||
{
|
||||
pktHdr.caplen = pktHdr.len = len;
|
||||
pktHdr.ts.tv_sec = pktHdr.ts.tv_usec = 0; // FIXME(HI)
|
||||
pktHdr.ts.tv_usec += ipg;
|
||||
if (pktHdr.ts.tv_usec > 1000000)
|
||||
{
|
||||
pktHdr.ts.tv_sec++;
|
||||
pktHdr.ts.tv_usec -= 1000000;
|
||||
}
|
||||
|
||||
if (-1 == pcap_sendqueue_queue(sendQueue, &pktHdr,
|
||||
(u_char*) pktBuf))
|
||||
@ -636,49 +651,7 @@ void PortInfo::update()
|
||||
|
||||
void PortInfo::startTransmit()
|
||||
{
|
||||
uint bytes, pkts;
|
||||
|
||||
// TODO(HI): Stream Mode - one pass/continuous
|
||||
// NOTE: Transmit on the Rx Handle so that we can receive it back
|
||||
// on the Tx Handle to do stats
|
||||
bytes = pcap_sendqueue_transmit(devHandleRx, sendQueue, false);
|
||||
if (bytes < sendQueue->len)
|
||||
{
|
||||
qDebug("port %d: sent (%d/%d) error %s. TxStats may be inconsistent",
|
||||
id(), bytes, sendQueue->len, pcap_geterr(devHandleTx));
|
||||
|
||||
// parse sendqueue using 'bytes' to get actual pkts sent
|
||||
#if 0
|
||||
// FIXME(LOW): Get this working
|
||||
pkts = qUpperBound(pcapExtra.sendQueueCumLen, bytes);
|
||||
#else
|
||||
for (int i = 0; i < pcapExtra.sendQueueCumLen.size(); i++)
|
||||
{
|
||||
if (pcapExtra.sendQueueCumLen.at(i) > bytes)
|
||||
{
|
||||
pkts = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug("port %d: sent (%d/%d) bytes\n", id(), bytes, sendQueue->len);
|
||||
pkts = pcapExtra.sendQueueCumLen.size();
|
||||
}
|
||||
|
||||
// pcap_sendqueue_transmit() returned 'bytes' includes size of pcap_pkthdr
|
||||
// - adjust for it
|
||||
if (bytes)
|
||||
bytes -= pkts * sizeof(pcap_pkthdr);
|
||||
#ifdef Q_OS_WIN32
|
||||
// Update pcapExtra counters - port TxStats will be updated in the
|
||||
// 'stats callback' function so that both Rx and Tx stats are updated
|
||||
// together
|
||||
pcapExtra.txPkts += pkts;
|
||||
pcapExtra.txBytes += bytes;
|
||||
#endif
|
||||
transmitter.start();
|
||||
}
|
||||
|
||||
void PortInfo::stopTransmit()
|
||||
@ -750,6 +723,11 @@ void PortInfo::PortMonitorRx::callbackRx(u_char *state,
|
||||
pkts = *((quint64*)(pkt_data + 0));
|
||||
bytes = *((quint64*)(pkt_data + 8));
|
||||
|
||||
#if 0
|
||||
if (port->id() == 2)
|
||||
qDebug("# %llu", pkts);
|
||||
#endif
|
||||
|
||||
// Note: PCAP reported bytes includes ETH_FRAME_HDR_SIZE - adjust for it
|
||||
bytes -= pkts * ETH_FRAME_HDR_SIZE;
|
||||
|
||||
@ -777,7 +755,7 @@ void PortInfo::PortMonitorRx::callbackRx(u_char *state,
|
||||
#endif
|
||||
|
||||
// Retreive NIC stats
|
||||
#ifdef Q_OS_WIN32
|
||||
#if 0
|
||||
port->monitorRx.oidData->Oid = OID_GEN_RCV_OK;
|
||||
if (PacketRequest(port->devHandleRx->adapter, 0, port->monitorRx.oidData))
|
||||
{
|
||||
@ -799,20 +777,28 @@ void PortInfo::PortMonitorTx::callbackTx(u_char *state,
|
||||
quint64 pkts;
|
||||
quint64 bytes;
|
||||
|
||||
|
||||
#if 0
|
||||
// Update RxStats and RxRates using PCAP data
|
||||
pkts = *((quint64*)(pkt_data + 0));
|
||||
bytes = *((quint64*)(pkt_data + 8));
|
||||
|
||||
#if 0
|
||||
if (port->id() == 2)
|
||||
qDebug("@ %llu", pkts);
|
||||
#endif
|
||||
|
||||
// Note: PCAP reported bytes includes ETH_FRAME_HDR_SIZE - adjust for it
|
||||
bytes -= pkts * ETH_FRAME_HDR_SIZE;
|
||||
|
||||
usec = (header->ts.tv_sec - port->lastTs.tv_sec) * 1000000 +
|
||||
(header->ts.tv_usec - port->lastTs.tv_usec);
|
||||
port->stats.rxPps = (pkts * 1000000) / usec;
|
||||
port->stats.rxBps = (bytes * 1000000) / usec;
|
||||
usec = (header->ts.tv_sec - port->lastTsTx.tv_sec) * 1000000 +
|
||||
(header->ts.tv_usec - port->lastTsTx.tv_usec);
|
||||
port->stats.txPps = (pkts * 1000000) / usec;
|
||||
port->stats.txBps = (bytes * 1000000) / usec;
|
||||
|
||||
port->stats.rxPkts += pkts;
|
||||
port->stats.rxBytes += bytes;
|
||||
port->stats.txPkts += pkts;
|
||||
port->stats.txBytes += bytes;
|
||||
#endif
|
||||
|
||||
// Since WinPCAP (due to NDIS limitation) cannot distinguish between
|
||||
// rx/tx packets, pcap stats are not of much use - for the tx stats
|
||||
@ -822,8 +808,8 @@ void PortInfo::PortMonitorTx::callbackTx(u_char *state,
|
||||
bytes = port->pcapExtra.txBytes - port->stats.txBytes;
|
||||
|
||||
// Use the pcap timestamp for rate calculation though
|
||||
usec = (header->ts.tv_sec - port->lastTs.tv_sec) * 1000000 +
|
||||
(header->ts.tv_usec - port->lastTs.tv_usec);
|
||||
usec = (header->ts.tv_sec - port->lastTsTx.tv_sec) * 1000000 +
|
||||
(header->ts.tv_usec - port->lastTsTx.tv_usec);
|
||||
port->stats.txPps = (pkts * 1000000) / usec;
|
||||
port->stats.txBps = (bytes * 1000000) / usec;
|
||||
|
||||
@ -846,7 +832,7 @@ void PortInfo::PortMonitorTx::callbackTx(u_char *state,
|
||||
#endif
|
||||
|
||||
// Retreive NIC stats
|
||||
#ifdef Q_OS_WIN32
|
||||
#if 0
|
||||
port->monitorTx.oidData->Oid = OID_GEN_XMIT_OK;
|
||||
if (PacketRequest(port->devHandleTx->adapter, 0, port->monitorTx.oidData))
|
||||
{
|
||||
@ -926,7 +912,7 @@ void PortInfo::PortMonitorRx::run()
|
||||
int ret;
|
||||
|
||||
qDebug("before pcap_loop rx \n");
|
||||
|
||||
#if 1
|
||||
/* Start the main loop */
|
||||
ret = pcap_loop(port->devHandleRx, -1,
|
||||
&PortInfo::PortMonitorRx::callbackRx, (u_char*) port);
|
||||
@ -945,6 +931,28 @@ void PortInfo::PortMonitorRx::run()
|
||||
default:
|
||||
qDebug("Unknown return value from pcap_loop()\n");
|
||||
}
|
||||
#else
|
||||
while (1)
|
||||
{
|
||||
/* Start the main loop */
|
||||
ret = pcap_dispatch(port->devHandleRx, -1,
|
||||
&PortInfo::PortMonitorRx::callbackRx, (u_char*) port);
|
||||
|
||||
switch(ret)
|
||||
{
|
||||
case -1:
|
||||
qDebug("Unsolicited (error) return from pcap_loop() %s\n",
|
||||
pcap_geterr(port->devHandleRx));
|
||||
break;
|
||||
case -2:
|
||||
qDebug("Solicited return from pcap_loop()\n");
|
||||
break;
|
||||
default:
|
||||
//qDebug("%d pkts rcvd\n", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PortInfo::PortMonitorTx::run()
|
||||
@ -952,7 +960,7 @@ void PortInfo::PortMonitorTx::run()
|
||||
int ret;
|
||||
|
||||
qDebug("before pcap_loopTx\n");
|
||||
|
||||
#if 1
|
||||
/* Start the main loop */
|
||||
ret = pcap_loop(port->devHandleTx, -1,
|
||||
&PortInfo::PortMonitorTx::callbackTx, (u_char*) port);
|
||||
@ -971,6 +979,84 @@ void PortInfo::PortMonitorTx::run()
|
||||
default:
|
||||
qDebug("Unknown return value from pcap_loop()\n");
|
||||
}
|
||||
#else
|
||||
while (1)
|
||||
{
|
||||
/* Start the main loop */
|
||||
ret = pcap_dispatch(port->devHandleTx, -1,
|
||||
&PortInfo::PortMonitorTx::callbackTx, (u_char*) port);
|
||||
|
||||
switch(ret)
|
||||
{
|
||||
case -1:
|
||||
qDebug("Unsolicited (error) return from pcap_loop() %s\n",
|
||||
pcap_geterr(port->devHandleTx));
|
||||
break;
|
||||
case -2:
|
||||
qDebug("Solicited return from pcap_loop()\n");
|
||||
break;
|
||||
default:
|
||||
//qDebug("%d pkts rcvd\n", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*--------------- PortTransmitter ---------------*/
|
||||
|
||||
PortInfo::PortTransmitter::PortTransmitter(PortInfo *port)
|
||||
{
|
||||
this->port = port;
|
||||
}
|
||||
|
||||
void PortInfo::PortTransmitter::run()
|
||||
{
|
||||
uint bytes, pkts;
|
||||
|
||||
// TODO(HI): Stream Mode - one pass/continuous
|
||||
// NOTE: Transmit on the Rx Handle so that we can receive it back
|
||||
// on the Tx Handle to do stats
|
||||
bytes = pcap_sendqueue_transmit(port->devHandleRx, port->sendQueue, true);
|
||||
if (bytes < port->sendQueue->len)
|
||||
{
|
||||
qDebug("port %d: sent (%d/%d) error %s. TxStats may be inconsistent",
|
||||
port->id(), bytes, port->sendQueue->len,
|
||||
pcap_geterr(port->devHandleTx));
|
||||
|
||||
// parse sendqueue using 'bytes' to get actual pkts sent
|
||||
#if 0
|
||||
// FIXME(LOW): Get this working
|
||||
pkts = qUpperBound(pcapExtra.sendQueueCumLen, bytes);
|
||||
#else
|
||||
for (int i = 0; i < port->pcapExtra.sendQueueCumLen.size(); i++)
|
||||
{
|
||||
if (port->pcapExtra.sendQueueCumLen.at(i) > bytes)
|
||||
{
|
||||
pkts = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug("port %d: sent (%d/%d) bytes\n", port->id(), bytes,
|
||||
port->sendQueue->len);
|
||||
pkts = port->pcapExtra.sendQueueCumLen.size();
|
||||
}
|
||||
|
||||
// pcap_sendqueue_transmit() returned 'bytes' includes size of pcap_pkthdr
|
||||
// - adjust for it
|
||||
if (bytes)
|
||||
bytes -= pkts * sizeof(pcap_pkthdr);
|
||||
#ifdef Q_OS_WIN32
|
||||
// Update pcapExtra counters - port TxStats will be updated in the
|
||||
// 'stats callback' function so that both Rx and Tx stats are updated
|
||||
// together
|
||||
port->pcapExtra.txPkts += pkts;
|
||||
port->pcapExtra.txBytes += bytes;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*--------------- MyService ---------------*/
|
||||
@ -1369,6 +1455,11 @@ const ::OstProto::PortIdList* request,
|
||||
s = response->add_port_stats();
|
||||
s->mutable_port_id()->set_id(request->port_id(i).id());
|
||||
|
||||
if (portidx == 2)
|
||||
{
|
||||
qDebug("<%llu", portInfo[portidx]->epochStats.rxPkts);
|
||||
qDebug(">%llu", portInfo[portidx]->stats.rxPkts);
|
||||
}
|
||||
s->set_rx_pkts(portInfo[portidx]->stats.rxPkts -
|
||||
portInfo[portidx]->epochStats.rxPkts);
|
||||
s->set_rx_bytes(portInfo[portidx]->stats.rxBytes -
|
||||
|
@ -82,6 +82,17 @@ class PortInfo
|
||||
const struct pcap_pkthdr *header, const u_char *pkt_data);
|
||||
void run();
|
||||
};
|
||||
|
||||
class PortTransmitter: public QThread
|
||||
{
|
||||
friend class PortInfo;
|
||||
|
||||
PortInfo *port;
|
||||
|
||||
public:
|
||||
PortTransmitter(PortInfo *port);
|
||||
void run();
|
||||
};
|
||||
|
||||
OstProto::Port d;
|
||||
|
||||
@ -111,7 +122,7 @@ class PortInfo
|
||||
//! Used to track num of packets (and their sizes) in the
|
||||
// send queue. Also used to find out actual num of pkts sent
|
||||
// in case of partial send in pcap_sendqueue_transmit()
|
||||
QList<uint> sendQueueCumLen;
|
||||
QList<uint> sendQueueCumLen;
|
||||
|
||||
//! PCAP doesn't do any tx stats
|
||||
quint64 txPkts;
|
||||
@ -121,11 +132,12 @@ class PortInfo
|
||||
pcap_if_t *dev;
|
||||
pcap_t *devHandleRx;
|
||||
pcap_t *devHandleTx;
|
||||
pcap_send_queue *sendQueue;
|
||||
pcap_send_queue* sendQueue;
|
||||
bool isSendQueueDirty;
|
||||
PcapExtra pcapExtra;
|
||||
PortMonitorRx monitorRx;
|
||||
PortMonitorTx monitorTx;
|
||||
PortTransmitter transmitter;
|
||||
|
||||
struct PortStats epochStats;
|
||||
struct PortStats stats;
|
||||
|
Loading…
Reference in New Issue
Block a user