Stream creation (various modes etc.) done except for Rate Control.

PortStats done - need to find solution for txRates
This commit is contained in:
Srivats P. 2008-09-28 18:01:52 +00:00
parent 4cf80d4ee4
commit 62a82dfb80
24 changed files with 1355 additions and 1071 deletions

View File

@ -18,10 +18,10 @@ MainWindow::MainWindow(QWidget *parent)
setupUi(this);
dock->setWidget(portsWindow);
addDockWidget(Qt::TopDockWidgetArea, dock);
dock2->setWidget(statsWindow);
addDockWidget(Qt::BottomDockWidgetArea, dock2);
dock->setWidget(portsWindow);
addDockWidget(Qt::TopDockWidgetArea, dock);
}
void MainWindow::on_actionPreferences_triggered()

View File

@ -6,7 +6,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
<height>650</height>
</rect>
</property>
<property name="windowTitle" >

View File

@ -20,6 +20,10 @@ Port::Port(quint32 id, quint32 portGroupId)
mPortGroupId = portGroupId;
}
Port::~Port()
{
}
void Port::updatePortConfig(OstProto::Port *port)
{
d.MergeFrom(*port);

View File

@ -35,6 +35,7 @@ public:
// FIXME(HIGH): default args is a hack for QList operations on Port
Port(quint32 id = 0xFFFFFFFF, quint32 pgId = 0xFFFFFFFF);
~Port();
quint32 portGroupId() const { return mPortGroupId; }
const QString& userAlias() const { return mUserAlias; }

View File

@ -82,6 +82,13 @@ void PortGroup::when_configApply(int portIndex, uint *cookie)
Q_ASSERT(portIndex < mPorts.size());
if (state() != QAbstractSocket::ConnectedState)
{
if (cookie != NULL)
delete cookie;
return;
}
if (cookie == NULL)
{
// cookie[0]: op [0 - delete, 1 - add, 2 - modify, 3 - Done!]
@ -414,22 +421,62 @@ void PortGroup::processModifyStreamAck(OstProto::Ack *ack)
// TODO(HI): Apply Button should now be disabled???!!!!???
}
void PortGroup::startTx(QList<uint> portList)
void PortGroup::startTx(QList<uint> *portList)
{
OstProto::PortIdList portIdList;
OstProto::Ack *ack = new OstProto::Ack;
OstProto::Ack *ack;
qDebug("In %s", __FUNCTION__);
for (int i = 0; i < portList.size(); i++)
if (state() != QAbstractSocket::ConnectedState)
return;
ack = new OstProto::Ack;
if (portList == NULL)
goto _exit;
else
{
for (int i = 0; i < portList->size(); i++)
{
OstProto::PortId *portId;
portId = portIdList.add_port_id();
portId->set_id(portList.at(i));
portId->set_id(portList->at(i));
}
}
serviceStub->startTx(rpcController, &portIdList, ack,
NewCallback(this, &PortGroup::processStartTxAck, ack));
_exit:
return;
}
void PortGroup::stopTx(QList<uint> *portList)
{
OstProto::PortIdList portIdList;
OstProto::Ack *ack;
qDebug("In %s", __FUNCTION__);
if (state() != QAbstractSocket::ConnectedState)
return;
ack = new OstProto::Ack;
if (portList == NULL)
goto _exit;
else
{
for (int i = 0; i < portList->size(); i++)
{
OstProto::PortId *portId;
portId = portIdList.add_port_id();
portId->set_id(portList->at(i));
}
}
serviceStub->stopTx(rpcController, &portIdList, ack,
NewCallback(this, &PortGroup::processStopTxAck, ack));
_exit:
return;
}
void PortGroup::processStartTxAck(OstProto::Ack *ack)
@ -439,19 +486,30 @@ void PortGroup::processStartTxAck(OstProto::Ack *ack)
delete ack;
}
void PortGroup::getPortStats()
void PortGroup::processStopTxAck(OstProto::Ack *ack)
{
OstProto::PortStatsList *portStatsList = new OstProto::PortStatsList;
qDebug("In %s", __FUNCTION__);
delete ack;
}
void PortGroup::getPortStats()
{
OstProto::PortStatsList *portStatsList;
//qDebug("In %s", __FUNCTION__);
if (state() != QAbstractSocket::ConnectedState)
return;
portStatsList = new OstProto::PortStatsList;
serviceStub->getStats(rpcController, &portIdList, portStatsList,
NewCallback(this, &PortGroup::processPortStatsList, portStatsList));
}
void PortGroup::processPortStatsList(OstProto::PortStatsList *portStatsList)
{
qDebug("In %s", __FUNCTION__);
//qDebug("In %s", __FUNCTION__);
if (rpcController->Failed())
{
@ -474,12 +532,30 @@ _error_exit:
delete portStatsList;
}
void PortGroup::clearPortStats()
void PortGroup::clearPortStats(QList<uint> *portList)
{
OstProto::Ack *ack = new OstProto::Ack;
OstProto::PortIdList portIdList;
OstProto::Ack *ack;
qDebug("In %s", __FUNCTION__);
if (state() != QAbstractSocket::ConnectedState)
return;
ack = new OstProto::Ack;
if (portList == NULL)
portIdList.CopyFrom(this->portIdList);
else
{
for (int i = 0; i < portList->size(); i++)
{
OstProto::PortId *portId;
portId = portIdList.add_port_id();
portId->set_id(portList->at(i));
}
}
serviceStub->clearStats(rpcController, &portIdList, ack,
NewCallback(this, &PortGroup::processClearStatsAck, ack));
}
@ -488,6 +564,9 @@ void PortGroup::processClearStatsAck(OstProto::Ack *ack)
{
qDebug("In %s", __FUNCTION__);
// Refresh stats immediately after a stats clear/reset
getPortStats();
delete ack;
}

View File

@ -70,12 +70,14 @@ public:
void processModifyStreamAck(OstProto::Ack *ack);
void startTx(QList<uint> portList);
void startTx(QList<uint> *portList = NULL);
void processStartTxAck(OstProto::Ack *ack);
void stopTx(QList<uint> *portList = NULL);
void processStopTxAck(OstProto::Ack *ack);
void getPortStats();
void processPortStatsList(OstProto::PortStatsList *portStatsList);
void clearPortStats();
void clearPortStats(QList<uint> *portList = NULL);
void processClearStatsAck(OstProto::Ack *ack);
signals:

View File

@ -5,8 +5,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>402</width>
<height>275</height>
<width>588</width>
<height>298</height>
</rect>
</property>
<property name="windowTitle" >
@ -71,8 +71,55 @@
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="movement" >
<enum>QListView::Free</enum>
</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>

View File

@ -105,6 +105,12 @@ 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();
@ -117,7 +123,15 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
case e_STAT_BYTE_RECV_RATE:
return stats.rx_bps();
case e_STAT_BYTES_RCVD_NIC:
return stats.rx_bytes_nic();
case e_STAT_BYTES_SENT_NIC:
return stats.tx_bytes_nic();
default:
qWarning("%s: Unhandled stats id %d\n", __FUNCTION__,
index.row());
return 0;
}
}
@ -140,15 +154,38 @@ QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, in
void PortStatsModel::portListFromIndex(QModelIndexList indices,
QList<PortGroupAndPortList> &portList)
{
int i, j;
QModelIndexList selectedCols(indices);
portList.clear();
for (int i = 0; i < indices.size(); i++)
//selectedCols = indices.selectedColumns();
for (i = 0; i < selectedCols.size(); i++)
{
//getDomainIndexes(indices.at(i), portGroupIdx, portIdx);
uint portGroupIdx, portIdx;
for (int j = 0; j < portList.size(); j++)
getDomainIndexes(selectedCols.at(i), portGroupIdx, portIdx);
for (j = 0; j < portList.size(); j++)
{
// FIXME(HI): Incomplete!!!!
if (portList[j].portGroupId == portGroupIdx)
break;
}
if (j >= portList.size())
{
// PortGroup Not found
PortGroupAndPortList p;
p.portGroupId = portGroupIdx;
p.portList.append(portIdx);
portList.append(p);
}
else
{
// PortGroup found
portList[j].portList.append(portIdx);
}
}
}
@ -193,5 +230,9 @@ void PortStatsModel::updateStats()
void PortStatsModel::when_portGroup_stats_update(quint32 portGroupId)
{
// FIXME(MED): update only the changed ports, not all
reset();
QModelIndex topLeft = index(0, 0, QModelIndex());
QModelIndex bottomRight = index(rowCount(), columnCount(), QModelIndex());
emit dataChanged(topLeft, bottomRight);
}

View File

@ -9,10 +9,14 @@ 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,
e_STAT_BYTES_RCVD_NIC,
e_STAT_BYTES_SENT_NIC,
e_STAT_MAX
} PortStat;
@ -21,10 +25,14 @@ 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)"
<< "Bytes Received (NIC)"
<< "Bytes Sent (NIC)"
);
class PortGroupList;
@ -44,6 +52,7 @@ class PortStatsModel : public QAbstractTableModel
int role = Qt::DisplayRole) const;
class PortGroupAndPortList {
public:
uint portGroupId;
QList<uint> portList;
};

View File

@ -14,7 +14,10 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
model = pgl->getPortStatsModel();
tvPortStats->setModel(model);
tvPortStats->horizontalHeader()->setMovable(true);
tvPortStats->verticalHeader()->resizeSections(QHeaderView::ResizeToContents);
tvPortStats->verticalHeader()->setHighlightSections(false);
tvPortStats->verticalHeader()->setDefaultSectionSize(
tvPortStats->verticalHeader()->minimumSectionSize());
}
PortStatsWindow::~PortStatsWindow()
@ -25,21 +28,34 @@ PortStatsWindow::~PortStatsWindow()
void PortStatsWindow::on_tbStartTransmit_clicked()
{
// TODO(MED): get selected ports
QList<PortStatsModel::PortGroupAndPortList> pgpl;
if (pgl->numPortGroups())
// Get selected ports
model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(),
pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
{
QList<uint> portIdList;
// FIXME(HI): Testing only!!!
portIdList.append(1); // MS Loopback adapter
pgl->portGroupByIndex(0).startTx(portIdList);
pgl->portGroupByIndex(pgpl.at(i).portGroupId).
startTx(&pgpl[i].portList);
}
}
void PortStatsWindow::on_tbStopTransmit_clicked()
{
// TODO(MED)
QList<PortStatsModel::PortGroupAndPortList> pgpl;
// Get selected ports
model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(),
pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
{
pgl->portGroupByIndex(pgpl.at(i).portGroupId).
startTx(&pgpl[i].portList);
}
}
void PortStatsWindow::on_tbStartCapture_clicked()
@ -59,7 +75,18 @@ void PortStatsWindow::on_tbViewCapture_clicked()
void PortStatsWindow::on_tbClear_clicked()
{
// TODO(MED)
QList<PortStatsModel::PortGroupAndPortList> portList;
// Get selected ports
model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(),
portList);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < portList.size(); i++)
{
pgl->portGroupByIndex(portList.at(i).portGroupId).
clearPortStats(&portList[i].portList);
}
}
void PortStatsWindow::on_tbClearAll_clicked()

View File

@ -5,6 +5,7 @@
#include <QAbstractItemModel>
#include "ui_portstatswindow.h"
#include "portgrouplist.h"
#include "portstatsmodel.h"
class PortStatsWindow : public QWidget, public Ui::PortStatsWindow
{
@ -16,7 +17,7 @@ public:
private:
PortGroupList *pgl;
QAbstractItemModel *model;
PortStatsModel *model;
private slots:
void on_tbStartTransmit_clicked();

View File

@ -11,6 +11,12 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
setupUi(this);
tvStreamList->horizontalHeader()->resizeSections(
QHeaderView::ResizeToContents);
tvStreamList->verticalHeader()->setDefaultSectionSize(
tvStreamList->verticalHeader()->minimumSectionSize());
// Populate Context Menu Actions
tvPortList->addAction(actionNew_Port_Group);
tvPortList->addAction(actionDelete_Port_Group);
tvPortList->addAction(actionConnect_Port_Group);
@ -40,6 +46,10 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
connect( tvPortList->selectionModel(),
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
plm->getStreamModel(), SLOT(setCurrentPortIndex(const QModelIndex&)));
// Initially we don't have any ports - so trigger selection of
// portgroup detail page
when_portView_currentChanged(QModelIndex(), QModelIndex());
}
PortsWindow::~PortsWindow()

View File

@ -951,6 +951,7 @@ Stream::Stream()
mId = 0xFFFFFFFF;
mCore = new OstProto::StreamCore;
mControl = new OstProto::StreamControl;
// mCore->set_port_id(0xFFFFFFFF);
// mCore->set_stream_id(mId);
@ -973,6 +974,8 @@ Stream::Stream()
mUdp = new UdpProtocol;
mIcmp = new IcmpProtocol;
mIgmp = new IgmpProtocol;
mCore->set_is_enabled(true);
}
void Stream::getConfig(uint portId, OstProto::Stream *s)
@ -980,6 +983,7 @@ void Stream::getConfig(uint portId, OstProto::Stream *s)
s->mutable_stream_id()->set_id(mId);
s->mutable_core()->CopyFrom(*mCore);
s->mutable_control()->CopyFrom(*mControl);
mMac->getConfig(s->mutable_mac());
mMac->getConfig(s->mutable_mac());
@ -997,6 +1001,29 @@ void Stream::getConfig(uint portId, OstProto::Stream *s)
mIgmp->getConfig(s->mutable_igmp());
}
bool Stream::update(OstProto::Stream *stream)
{
mCore->MergeFrom(stream->core());
mControl->MergeFrom(stream->control());
mMac->update(stream->mac());
mLlc->update(stream->llc());
mSnap->update(stream->snap());
mEth2->update(stream->eth2());
mVlan->update(stream->vlan());
mIp->update(stream->ip());
mArp->update(stream->arp());
mTcp->update(stream->tcp());
mUdp->update(stream->udp());
mIcmp->update(stream->icmp());
mIgmp->update(stream->igmp());
// FIXME(MED): Re-eval why not store complete OstProto::Stream
// instead of components
return true;
}
// FIXME(HIGH): Replace this by some Protocol Registration mechanism at Init
#define PTYP_L2_NONE 1
#define PTYP_L2_ETH_2 2

View File

@ -831,6 +831,7 @@ class Stream {
quint32 mId;
OstProto::StreamCore *mCore;
OstProto::StreamControl *mControl;
UnknownProtocol *mUnknown;
PayloadProtocol *mPayload;
@ -909,6 +910,22 @@ public:
e_l4_igmp,
};
enum SendUnit {
e_su_packets,
e_su_bursts
};
enum SendMode {
e_sm_fixed,
e_sm_continuous
};
enum NextWhat {
e_nw_stop,
e_nw_goto_next,
e_nw_goto_id
};
// -------------------------------------------------------
// Methods
// -------------------------------------------------------
@ -917,30 +934,9 @@ public:
bool operator < (const Stream &s) const
{ return(mCore->ordinal() < s.mCore->ordinal()); }
bool update(OstProto::Stream *stream)
{
mCore->MergeFrom(stream->core());
mMac->update(stream->mac());
mLlc->update(stream->llc());
mSnap->update(stream->snap());
mEth2->update(stream->eth2());
mVlan->update(stream->vlan());
mIp->update(stream->ip());
mArp->update(stream->arp());
mTcp->update(stream->tcp());
mUdp->update(stream->udp());
mIcmp->update(stream->icmp());
mIgmp->update(stream->igmp());
// FIXME(MED): Re-eval why not store complete OstProto::Stream
// instead of components
return true;
}
void getConfig(uint portId, OstProto::Stream *s);
bool update(OstProto::Stream *stream);
quint32 id()
{ return mId;}
@ -1025,6 +1021,48 @@ public:
{ mCore->set_l4_proto((OstProto::StreamCore::L4Proto) l4Proto);
return true; }
SendUnit sendUnit()
{ return (SendUnit) mControl->unit(); }
bool setSendUnit(SendUnit sendUnit)
{ mControl->set_unit(
(OstProto::StreamControl::SendUnit) sendUnit); return true; }
SendMode sendMode()
{ return (SendMode) mControl->mode(); }
bool setSendMode(SendMode sendMode)
{ mControl->set_mode(
(OstProto::StreamControl::SendMode) sendMode); return true; }
NextWhat nextWhat()
{ return (NextWhat) mControl->next(); }
bool setNextWhat(NextWhat nextWhat)
{ mControl->set_next(
(OstProto::StreamControl::NextWhat) nextWhat); return true; }
quint32 numPackets()
{ return (quint32) mControl->num_packets(); }
bool setNumPackets(quint32 numPackets)
{ mControl->set_num_packets(numPackets); return true; }
quint32 numBursts()
{ return (quint32) mControl->num_bursts(); }
bool setNumBursts(quint32 numBursts)
{ mControl->set_num_bursts(numBursts); return true; }
quint32 burstSize()
{ return (quint32) mControl->packets_per_burst(); }
bool setBurstSize(quint32 packetsPerBurst)
{ mControl->set_packets_per_burst(packetsPerBurst); return true; }
quint32 packetRate()
{ return (quint32) mControl->packets_per_sec(); }
bool setPacketRate(quint32 packetsPerSec)
{ mControl->set_packets_per_sec(packetsPerSec); return true; }
quint32 burstRate()
{ return (quint32) mControl->bursts_per_sec(); }
bool setBurstRate(quint32 burstsPerSec)
{ mControl->set_bursts_per_sec(burstsPerSec); return true; }
//---------------------------------------------------------------
// Methods for use by Packet Model

View File

@ -13,6 +13,112 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
setupUi(this);
setupUiExtra();
// Time to play match the signals and slots!
connect(rbFtNone, SIGNAL(toggled(bool)), rbL3None, SLOT(setChecked(bool)));
// Show/Hide FrameType related inputs for FT None
connect(rbFtNone, SIGNAL(toggled(bool)), lblDsap, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), leDsap, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), lblSsap, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), leSsap, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), lblControl, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), leControl, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), lblOui, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), leOui, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), lblType, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), leType, SLOT(setHidden(bool)));
// Show/Hide FrameType related inputs for FT Ethernet2
connect(rbFtEthernet2, SIGNAL(toggled(bool)), lblDsap, SLOT(setHidden(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), leDsap, SLOT(setHidden(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), lblSsap, SLOT(setHidden(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), leSsap, SLOT(setHidden(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), lblControl, SLOT(setHidden(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), leControl, SLOT(setHidden(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), lblOui, SLOT(setHidden(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), leOui, SLOT(setHidden(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), lblType, SLOT(setVisible(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), leType, SLOT(setVisible(bool)));
// Show/Hide FrameType related inputs for FT 802.3 Raw
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), lblDsap, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), leDsap, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), lblSsap, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), leSsap, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), lblControl, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), leControl, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), lblOui, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), leOui, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), lblType, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), leType, SLOT(setHidden(bool)));
// Show/Hide FrameType related inputs for FT 802.3 LLC
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), lblDsap, SLOT(setVisible(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), leDsap, SLOT(setVisible(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), lblSsap, SLOT(setVisible(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), leSsap, SLOT(setVisible(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), lblControl, SLOT(setVisible(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), leControl, SLOT(setVisible(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), lblOui, SLOT(setHidden(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), leOui, SLOT(setHidden(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), lblType, SLOT(setHidden(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), leType, SLOT(setHidden(bool)));
// Show/Hide FrameType related inputs for FT 802.3 LLC SNAP
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblDsap, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leDsap, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblSsap, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leSsap, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblControl, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leControl, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblOui, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leOui, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblType, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leType, SLOT(setVisible(bool)));
// Enable/Disable FrameType related inputs for FT 802.3 LLC SNAP
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblDsap, SLOT(setDisabled(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leDsap, SLOT(setDisabled(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblSsap, SLOT(setDisabled(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leSsap, SLOT(setDisabled(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblControl, SLOT(setDisabled(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leControl, SLOT(setDisabled(bool)));
// Enable/Disable L4 Protocol Choices for L3 Protocol None
connect(rbL3None, SIGNAL(toggled(bool)), rbL4None, SLOT(setEnabled(bool)));
connect(rbL3None, SIGNAL(toggled(bool)), rbL4Icmp, SLOT(setDisabled(bool)));
connect(rbL3None, SIGNAL(toggled(bool)), rbL4Igmp, SLOT(setDisabled(bool)));
connect(rbL3None, SIGNAL(toggled(bool)), rbL4Tcp, SLOT(setDisabled(bool)));
connect(rbL3None, SIGNAL(toggled(bool)), rbL4Udp, SLOT(setDisabled(bool)));
connect(rbL3None, SIGNAL(toggled(bool)), rbL4Other, SLOT(setDisabled(bool)));
// Force L4 Protocol = None if L3 Protocol is set to None
connect(rbL3None, SIGNAL(toggled(bool)), rbL4None, SLOT(setChecked(bool)));
// Enable/Disable L4 Protocol Choices for L3 Protocol IPv4
connect(rbL3Ipv4, SIGNAL(toggled(bool)), rbL4None, SLOT(setEnabled(bool)));
connect(rbL3Ipv4, SIGNAL(toggled(bool)), rbL4Icmp, SLOT(setEnabled(bool)));
connect(rbL3Ipv4, SIGNAL(toggled(bool)), rbL4Igmp, SLOT(setEnabled(bool)));
connect(rbL3Ipv4, SIGNAL(toggled(bool)), rbL4Tcp, SLOT(setEnabled(bool)));
connect(rbL3Ipv4, SIGNAL(toggled(bool)), rbL4Udp, SLOT(setEnabled(bool)));
connect(rbL3Ipv4, SIGNAL(toggled(bool)), rbL4Other, SLOT(setEnabled(bool)));
// Enable/Disable L4 Protocol Choices for L3 Protocol ARP
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4None, SLOT(setEnabled(bool)));
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4Icmp, SLOT(setDisabled(bool)));
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4Igmp, SLOT(setDisabled(bool)));
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4Tcp, SLOT(setDisabled(bool)));
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4Udp, SLOT(setDisabled(bool)));
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4Other, SLOT(setDisabled(bool)));
// Force L4 Protocol = None if L3 Protocol is set to ARP
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4None, SLOT(setChecked(bool)));
// Init with FT=Eth2 to trigger signals; actual value will be
// initialized by LoadCurrentStream()
rbFtEthernet2->click();
rbFtNone->click();
//mpStreamList = streamList;
mCurrentStreamIndex = streamIndex;
LoadCurrentStream();
@ -24,9 +130,16 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
vwPacketDump->setModel(mpPacketModel);
vwPacketDump->setSelectionModel(tvPacketTree->selectionModel());
// FIXME(MED): Enable this navigation
// TODO(MED):
//! \todo Enable navigation of streams
pbPrev->setDisabled(true);
pbNext->setDisabled(true);
//! \todo Support Goto Stream Id
rbActionGotoStream->setDisabled(true);
//! \todo Support Continuous Mode
rbModeContinuous->setDisabled(true);
}
void StreamConfigDialog::setupUiExtra()
@ -128,6 +241,22 @@ void StreamConfigDialog::on_pbNext_clicked()
#endif
}
void StreamConfigDialog::on_rbFtNone_toggled(bool checked)
{
}
void StreamConfigDialog::on_rbFtEthernet2_toggled(bool checked)
{
}
void StreamConfigDialog::on_rbFt802Dot3Raw_toggled(bool checked)
{
}
void StreamConfigDialog::on_rbFt802Dot3Llc_toggled(bool checked)
{
}
void StreamConfigDialog::on_rbFtLlcSnap_toggled(bool checked)
{
if (checked)
@ -551,6 +680,55 @@ void StreamConfigDialog::LoadCurrentStream()
// TODO(LOW)
}
}
// Stream Control
{
switch (pStream->sendUnit())
{
case Stream::e_su_packets:
rbSendPackets->setChecked(true);
break;
case Stream::e_su_bursts:
rbSendBursts->setChecked(true);
break;
default:
qWarning("Unhandled sendUnit = %d\n", pStream->sendUnit());
}
switch (pStream->sendMode())
{
case Stream::e_sm_fixed:
rbModeFixed->setChecked(true);
break;
case Stream::e_sm_continuous:
rbModeContinuous->setChecked(true);
break;
default:
qWarning("Unhandled sendMode = %d\n", pStream->sendMode());
}
switch(pStream->nextWhat())
{
case Stream::e_nw_stop:
rbActionStop->setChecked(true);
break;
case Stream::e_nw_goto_next:
rbActionGotoNext->setChecked(true);
break;
case Stream::e_nw_goto_id:
rbActionGotoStream->setChecked(true);
break;
default:
qWarning("Unhandled nextAction = %d\n", pStream->nextWhat());
}
leNumPackets->setText(QString().setNum(pStream->numPackets()));
leNumBursts->setText(QString().setNum(pStream->numBursts()));
lePacketsPerBurst->setText(QString().setNum(
pStream->burstSize()));
lePacketsPerSec->setText(QString().setNum(pStream->packetRate()));
leBurstsPerSec->setText(QString().setNum(pStream->burstRate()));
}
}
void StreamConfigDialog::StoreCurrentStream()
@ -623,11 +801,14 @@ void StreamConfigDialog::StoreCurrentStream()
{
// L2 | Ethernet
{
qDebug("%s: LL dstMac = %llx", __FUNCTION__,
leDstMac->text().remove(QChar(' ')).toULongLong(&isOk, 16));
pStream->mac()->setDstMac(
leDstMac->text().remove(QChar(' ')).toULongLong(&isOk, 16));
#if 1
qDebug("%s: dstMac = %llx [%s] %d", __FUNCTION__,
pStream->mac()->dstMac(),
qDebug("%s: dstMac = %llx", __FUNCTION__,
pStream->mac()->dstMac());
qDebug("%s: dstMac = [%s] %d", __FUNCTION__,
leDstMac->text().toAscii().constData(), isOk);
#endif
pStream->mac()->setDstMacMode(
@ -639,8 +820,9 @@ void StreamConfigDialog::StoreCurrentStream()
pStream->mac()->setSrcMac(
leSrcMac->text().remove(QChar(' ')).toULongLong(&isOk, 16));
qDebug("%s: srcMac = %llx [%s] %d", __FUNCTION__,
pStream->mac()->srcMac(),
qDebug("%s: srcMac = %llx", __FUNCTION__,
pStream->mac()->srcMac());
qDebug("%s: srcMac = [%s] %d", __FUNCTION__,
leSrcMac->text().toAscii().constData(), isOk);
pStream->mac()->setSrcMacMode(
(MacProtocol::MacAddrMode) cmbSrcMacMode->currentIndex());
@ -657,7 +839,7 @@ void StreamConfigDialog::StoreCurrentStream()
vlan->setCvlanPrio(cmbCvlanPrio->currentIndex());
vlan->setCvlanCfi(cmbCvlanCfi->currentIndex());
vlan->setCvlanId(leCvlanId->text().toULong(&isOk));
vlan->setCtpid(leCvlanTpid->text().remove(QChar(' ')).toULong(&isOk));
vlan->setCtpid(leCvlanTpid->text().remove(QChar(' ')).toULong(&isOk, 16));
if (cbCvlanTpidOverride->isChecked())
f |= VlanProtocol::VlanCtpidOverride;
if (gbCvlan->isChecked())
@ -666,7 +848,7 @@ void StreamConfigDialog::StoreCurrentStream()
vlan->setSvlanPrio(cmbSvlanPrio->currentIndex());
vlan->setSvlanCfi(cmbSvlanCfi->currentIndex());
vlan->setSvlanId(leSvlanId->text().toULong(&isOk));
vlan->setStpid(leSvlanTpid->text().remove(QChar(' ')).toULong(&isOk));
vlan->setStpid(leSvlanTpid->text().remove(QChar(' ')).toULong(&isOk, 16));
if (cbSvlanTpidOverride->isChecked())
f |= VlanProtocol::VlanStpidOverride;
if (gbSvlan->isChecked())
@ -798,6 +980,32 @@ void StreamConfigDialog::StoreCurrentStream()
// TODO(LOW)
}
}
// Stream Control
{
if (rbSendPackets->isChecked())
pStream->setSendUnit(Stream::e_su_packets);
if (rbSendBursts->isChecked())
pStream->setSendUnit(Stream::e_su_bursts);
if (rbModeFixed->isChecked())
pStream->setSendMode(Stream::e_sm_fixed);
if (rbModeContinuous->isChecked())
pStream->setSendMode(Stream::e_sm_continuous);
if (rbActionStop->isChecked())
pStream->setNextWhat(Stream::e_nw_stop);
if (rbActionGotoNext->isChecked())
pStream->setNextWhat(Stream::e_nw_goto_next);
if (rbActionGotoStream->isChecked())
pStream->setNextWhat(Stream::e_nw_goto_id);
pStream->setNumPackets(leNumPackets->text().toULong(&isOk));
pStream->setNumBursts(leNumBursts->text().toULong(&isOk));
pStream->setBurstSize(lePacketsPerBurst->text().toULong(&isOk));
pStream->setPacketRate(lePacketsPerSec->text().toULong(&isOk));
pStream->setBurstRate(leBurstsPerSec->text().toULong(&isOk));
}
}
void StreamConfigDialog::on_pbOk_clicked()

View File

@ -44,6 +44,10 @@ private slots:
void on_pbPrev_clicked();
void on_pbNext_clicked();
void on_rbFtNone_toggled(bool checked);
void on_rbFtEthernet2_toggled(bool checked);
void on_rbFt802Dot3Raw_toggled(bool checked);
void on_rbFt802Dot3Llc_toggled(bool checked);
void on_rbFtLlcSnap_toggled(bool checked);
void on_rbL3Ipv4_toggled(bool checked);

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,10 @@ Qt::ItemFlags StreamModel::flags(const QModelIndex &index) const
flags |= Qt::ItemIsEditable;
break;
case StreamStatus:
#if 0
flags |= Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
#endif
flags |= Qt::ItemIsEditable;
break;
default:
break;
@ -87,11 +90,11 @@ QVariant StreamModel::data(const QModelIndex &index, int role) const
}
case StreamStatus:
{
#if 0
if ((role == Qt::DisplayRole) || (role == Qt::EditRole))
return streamList[index.row()].isEnabled;
if ((role == Qt::DisplayRole) || (role == Qt::CheckStateRole) ||
#endif
return mCurrentPort->streamByIndex(index.row()).isEnabled();
else
return QVariant();
#if 0
if ((role == Qt::CheckStateRole) || (role == Qt::EditRole))
{
if (mCurrentPort->streamByIndex(index.row()).isEnabled())
@ -101,6 +104,7 @@ QVariant StreamModel::data(const QModelIndex &index, int role) const
}
else
return QVariant();
#endif
break;
}
default:

View File

@ -109,7 +109,7 @@ message Tcp {
optional uint32 dst_port = 4 [default = 80];
optional uint32 seq_num = 5 [default = 129018];
optional uint32 ack_num = 6 [default = 98223];
optional uint32 ack_num = 6;
optional uint32 hdrlen_rsvd = 7 [default = 0x50];
optional uint32 flags = 8;
@ -138,6 +138,9 @@ message Icmp {
message Igmp {
}
message StreamId {
required uint32 id = 1;
}
message StreamCore {
@ -201,14 +204,41 @@ message StreamCore {
optional L4Proto l4_proto = 23;
}
message StreamId {
required uint32 id = 1;
message StreamControl {
enum SendUnit {
e_su_packets = 0;
e_su_bursts = 1;
}
enum SendMode {
e_sm_fixed = 0;
e_sm_continuous = 1;
}
enum NextWhat {
e_nw_stop = 0;
e_nw_goto_next = 1;
e_nw_goto_id = 2;
}
optional SendUnit unit = 1 [default = e_su_packets];
optional SendMode mode = 2 [default = e_sm_fixed];
optional uint32 num_packets = 3 [default = 1];
optional uint32 num_bursts = 4 [default = 1];
optional uint32 packets_per_burst = 5 [default = 10];
optional NextWhat next = 6 [default = e_nw_goto_next];
optional uint32 packets_per_sec = 7;
optional uint32 bursts_per_sec = 8;
// TODO: Gaps?
}
message Stream {
required StreamId stream_id = 1;
optional StreamCore core = 2;
optional StreamControl control = 3;
// Protocol data - L2
optional Mac mac = 51;
@ -283,13 +313,17 @@ message PortStats {
optional uint64 rx_pkts = 11;
optional uint64 rx_bytes = 12;
optional uint64 rx_pps = 13;
optional uint64 rx_bps = 14;
optional uint64 rx_pkts_nic = 13;
optional uint64 rx_bytes_nic = 14;
optional uint64 rx_pps = 15;
optional uint64 rx_bps = 16;
optional uint64 tx_pkts = 21;
optional uint64 tx_bytes = 22;
optional uint64 tx_pps = 23;
optional uint64 tx_bps = 24;
optional uint64 tx_pkts_nic = 23;
optional uint64 tx_bytes_nic = 24;
optional uint64 tx_pps = 25;
optional uint64 tx_bps = 26;
}
message PortStatsList {

View File

@ -69,7 +69,7 @@ void PbRpcChannel::CallMethod(
char *p = (char *)&msg;
int len;
qDebug("In %s", __FUNCTION__);
//qDebug("In %s", __FUNCTION__);
if (!req->IsInitialized())
{
@ -88,8 +88,8 @@ void PbRpcChannel::CallMethod(
isPending = true;
*((quint16*)(p+0)) = HTONS(PB_MSG_TYPE_REQUEST); // type
qDebug("CLi:GET16 = %d/%d, type = %d", GET16(p+0), NTOHS(GET16(p+0)),
PB_MSG_TYPE_REQUEST);
//qDebug("CLi:GET16 = %d/%d, type = %d", GET16(p+0), NTOHS(GET16(p+0)),
//PB_MSG_TYPE_REQUEST);
*((quint16*)(p+2)) = HTONS(method->index()); // method id
// (p+4) len later after serialization
*((quint16*)(p+6)) = HTONS(0); // rsvd
@ -100,9 +100,13 @@ void PbRpcChannel::CallMethod(
len = req->ByteSize();
*((quint16*)(p+4)) = HTONS(len); // len
// Avoid printing stats since it happens every couple of seconds
if (pendingMethodId != 12)
{
qDebug("client(%s) sending %d bytes encoding <%s>", __FUNCTION__, len+8,
req->DebugString().c_str());
BUFDUMP(msg, len+8);
}
mpSocket->write(msg, len + 8);
}
@ -115,12 +119,12 @@ void PbRpcChannel::on_mpSocket_readyRead()
quint16 type, method, len, rsvd;
PbRpcController *controller;
qDebug("In %s", __FUNCTION__);
//qDebug("In %s", __FUNCTION__);
msgLen = mpSocket->read(msg, sizeof(msg));
qDebug("client(%s) rcvd %d bytes", __FUNCTION__, msgLen);
BUFDUMP(msg, msgLen);
//qDebug("client(%s) rcvd %d bytes", __FUNCTION__, msgLen);
//BUFDUMP(msg, msgLen);
type = NTOHS(GET16(p+0));
method = NTOHS(GET16(p+2));
@ -153,8 +157,13 @@ void PbRpcChannel::on_mpSocket_readyRead()
// Serialized data starts from offset 8
response->ParseFromArray((void*) &msg[8], len);
// Avoid printing stats
if (method != 12)
{
qDebug("client(%s): Parsed as %s", __FUNCTION__,
response->DebugString().c_str());
}
if (!response->IsInitialized())
{

View File

@ -41,7 +41,7 @@ void RpcServer::done(::google::protobuf::Message *resp, PbRpcController *PbRpcCo
char *p = (char *)&msg;
int len;
qDebug("In RpcServer::done");
//qDebug("In RpcServer::done");
// TODO: check PbRpcController to see if method failed
if (PbRpcController->Failed())
@ -67,9 +67,13 @@ void RpcServer::done(::google::protobuf::Message *resp, PbRpcController *PbRpcCo
len = resp->ByteSize();
(*(quint16*)(p+4)) = HTONS(len); // len
// Avoid printing stats since it happens once every couple of seconds
if (pendingMethodId != 12)
{
qDebug("Server(%s): sending %d bytes to client encoding <%s>",
__FUNCTION__, len + 8, resp->DebugString().c_str());
//BUFDUMP(msg, len + 8);
}
clientSock->write(msg, len + 8);
@ -132,17 +136,17 @@ void RpcServer::when_dataAvail()
PbRpcController *controller;
msgLen = clientSock->read(msg, sizeof(msg));
LogInt(QString(QByteArray(msg, msgLen).toHex()));
//LogInt(QString(QByteArray(msg, msgLen).toHex()));
qDebug("Server %s: rcvd %d bytes", __FUNCTION__, msgLen);
//qDebug("Server %s: rcvd %d bytes", __FUNCTION__, msgLen);
//BUFDUMP(msg, msgLen);
type = NTOHS(GET16(p+0));
method = NTOHS(GET16(p+2));
len = NTOHS(GET16(p+4));
rsvd = NTOHS(GET16(p+6));
qDebug("type = %d, method = %d, len = %d, rsvd = %d",
type, method, len, rsvd);
//qDebug("type = %d, method = %d, len = %d, rsvd = %d",
//type, method, len, rsvd);
if (type != PB_MSG_TYPE_REQUEST)
{
@ -182,12 +186,12 @@ void RpcServer::when_dataAvail()
goto _error_exit;
}
qDebug("Server(%s): successfully parsed as <%s>", __FUNCTION__,
resp->DebugString().c_str());
//qDebug("Server(%s): successfully parsed as <%s>", __FUNCTION__,
//resp->DebugString().c_str());
controller = new PbRpcController;
qDebug("before service->callmethod()");
//qDebug("before service->callmethod()");
service->CallMethod(methodDesc, controller, req, resp,
NewCallback(this, &RpcServer::done, resp, controller));

View File

@ -5,7 +5,7 @@ DEFINES += HAVE_REMOTE WPCAP
INCLUDEPATH += "c:\msys\1.0\local\include"
INCLUDEPATH += "C:\DevelLibs\WpdPack\Include"
INCLUDEPATH += "..\rpc"
LIBS += -L"C:\DevelLibs\WpdPack\Lib" -lwpcap
LIBS += -L"C:\DevelLibs\WpdPack\Lib" -lwpcap -lpacket
LIBS += -L"..\rpc\debug" -lpbrpc
HEADERS += drone.h
FORMS += drone.ui

View File

@ -1,30 +1,177 @@
#include "myservice.h"
#include "qdebug.h"
#include <qglobal.h>
#include <qendian.h>
#ifdef Q_OS_WIN32
#include <pcap-int.h>
#include <Ntddndis.h>
#endif
#define LOG(...) {sprintf(logStr, __VA_ARGS__); host->Log(logStr);}
#define MB (1024*1024)
int StreamInfo::makePacket(uchar *buf, int bufMaxSize)
#if 0
quint16 StreamInfo::ipv4Cksum(quint16 ipHdrLen, quint16 buff[])
{
int pktLen, len = 0;
quint16 word16;
quint32 sum=0;
quint16 i;
// make 16 bit words out of every two adjacent 8 bit words in the packet
// and add them up
for (i = 0; i < ipHdrLen ;i += 2)
{
word16 =((buff[i]<<8)&0xFF00)+(buff[i+1]&0xFF);
sum = sum + (quint32) word16;
}
// take only 16 bits out of the 32 bit sum and add up the carries
while (sum>>16)
sum = (sum & 0xFFFF)+(sum >> 16);
// one's complement the result
sum = ~sum;
return (quint16) sum;
}
#endif
quint16 StreamInfo::ipv4Cksum(uchar *buf, int len)
{
quint32 sum = 0; /* assume 32 bit long, 16 bit short */
quint16 *ip = (quint16*) buf;
while(len > 1)
{
sum += *ip;
if(sum & 0x80000000) /* if high order bit set, fold */
sum = (sum & 0xFFFF) + (sum >> 16);
ip++;
len -= 2;
}
if(len) /* take care of left over byte */
sum += (unsigned short) *(unsigned char *)ip;
while(sum>>16)
sum = (sum & 0xFFFF) + (sum >> 16);
qDebug("cksum = %x", ~sum);
return (quint16) ~sum;
}
int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
{
int u, pktLen, len = 0;
uchar scratch[8];
// TODO(HI): use FrameLengthMode - don't assume fixed
pktLen = d.core().frame_len();
// pktLen is adjusted for CRC/FCS which will be added by the NIC
pktLen = d.core().frame_len() - 4;
if (bufMaxSize < pktLen)
return 0;
// We always have a Mac Header!
// TODO(HI): use MacMode - don't assume fixed
switch (d.mac().dst_mac_mode())
{
case OstProto::Mac::e_mm_fixed:
qToBigEndian((quint64) d.mac().dst_mac(), scratch);
break;
case OstProto::Mac::e_mm_inc:
u = (n % d.mac().dst_mac_count()) * d.mac().dst_mac_step();
qToBigEndian((quint64) d.mac().dst_mac() + u, scratch);
break;
case OstProto::Mac::e_mm_dec:
u = (n % d.mac().dst_mac_count()) * d.mac().dst_mac_step();
qToBigEndian((quint64) d.mac().dst_mac() - u, scratch);
break;
default:
qWarning("Unhandled dstMac_mode %d", d.mac().dst_mac_mode());
}
memcpy((buf + len), scratch + 2, 6);
len += 6;
switch (d.mac().src_mac_mode())
{
case OstProto::Mac::e_mm_fixed:
qToBigEndian((quint64) d.mac().src_mac(), scratch);
memcpy((buf + len), &scratch + 2, 6);
break;
case OstProto::Mac::e_mm_inc:
u = (n % d.mac().src_mac_count()) * d.mac().src_mac_step();
qToBigEndian((quint64) d.mac().src_mac() + u, scratch);
break;
case OstProto::Mac::e_mm_dec:
u = (n % d.mac().src_mac_count()) * d.mac().src_mac_step();
qToBigEndian((quint64) d.mac().src_mac() - u, scratch);
break;
default:
qWarning("Unhandled srcMac_mode %d", d.mac().src_mac_mode());
}
memcpy((buf + len), scratch + 2, 6);
len += 6;
// Frame Type - Part 1 (pre VLAN info)
switch(d.core().ft())
{
case OstProto::StreamCore::e_ft_none:
case OstProto::StreamCore::e_ft_eth_2:
break;
case OstProto::StreamCore::e_ft_802_3_raw:
qToBigEndian((quint16) pktLen, buf+len);
len += 2;
break;
case OstProto::StreamCore::e_ft_802_3_llc:
qToBigEndian((quint16) pktLen, buf+len);
len += 2;
buf[len+0] = (quint8) d.llc().dsap();
buf[len+1] = (quint8) d.llc().ssap();
buf[len+2] = (quint8) d.llc().ctl();
len +=3;
break;
case OstProto::StreamCore::e_ft_snap:
qToBigEndian((quint16) pktLen, buf+len);
len += 2;
buf[len+0] = (quint8) d.llc().dsap();
buf[len+1] = (quint8) d.llc().ssap();
buf[len+2] = (quint8) d.llc().ctl();
len +=3;
qToBigEndian((quint32) d.snap().oui(), scratch);
memcpy((buf + len), scratch + 2, 3);
len += 3;
break;
default:
qWarning("Unhandled frame type %d\n", d.core().ft());
}
// VLAN
if (d.vlan().is_svlan_tagged())
{
if (d.vlan().is_stpid_override())
qToBigEndian((quint16) d.vlan().stpid(), buf+len);
else
qToBigEndian((quint16) 0x88a8, buf+len);
len += 2 ;
qToBigEndian((quint16) d.vlan().svlan_tag(), buf+len);
len += 2 ;
}
if (d.vlan().is_cvlan_tagged())
{
if (d.vlan().is_ctpid_override())
qToBigEndian((quint16) d.vlan().ctpid(), buf+len);
else
qToBigEndian((quint16) 0x8100, buf+len);
len += 2 ;
qToBigEndian((quint16) d.vlan().cvlan_tag(), buf+len);
len += 2 ;
}
// Frame Type - Part 2 (post VLAN info)
switch(d.core().ft())
{
case OstProto::StreamCore::e_ft_none:
@ -34,23 +181,9 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize)
len += 2;
break;
case OstProto::StreamCore::e_ft_802_3_raw:
qToBigEndian((quint16) pktLen, buf+len);
len += 2;
break;
case OstProto::StreamCore::e_ft_802_3_llc:
buf[len+0] = (quint8) d.llc().dsap();
buf[len+1] = (quint8) d.llc().ssap();
buf[len+2] = (quint8) d.llc().ctl();
len +=3;
break;
case OstProto::StreamCore::e_ft_snap:
buf[len+0] = (quint8) d.llc().dsap();
buf[len+1] = (quint8) d.llc().ssap();
buf[len+2] = (quint8) d.llc().ctl();
len +=3;
qToBigEndian((quint32) d.snap().oui(), scratch);
memcpy((buf + len), scratch + 2, 3);
len += 3;
qToBigEndian((quint16) d.eth2().type(), buf+len);
len += 2;
break;
@ -58,32 +191,107 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize)
qWarning("Unhandled frame type %d\n", d.core().ft());
}
// L3
switch (d.core().l3_proto())
{
case OstProto::StreamCore::e_l3_none:
break;
case OstProto::StreamCore::e_l3_ip:
{
quint32 subnet, host;
int ipOfs = len;
buf[len+0] = (quint8) (d.ip().ver_hdrlen());
buf[len+1] = (quint8) (d.ip().tos());
len += 2;
if (d.ip().is_override_totlen())
qToBigEndian((quint16) d.ip().tot_len(), buf+len);
else
qToBigEndian((quint16) (pktLen - ipOfs), buf+len);
len += 2;
qToBigEndian((quint16) d.ip().id(), buf+len);
len += 2;
qToBigEndian((quint16) (( (d.ip().flags() & 0x3) << 13) |
(d.ip().frag_ofs() & 0x1FFF)), buf+len);
len += 2;
buf[len+0] = (quint8) (d.ip().ttl());
buf[len+1] = (quint8) (d.ip().proto());
len += 2;
qToBigEndian((quint16) d.ip().cksum(), buf+len);
// cksum calculated after filling in the rest
qToBigEndian((quint16) 0, buf+len);
len += 2;
// TODO(HI): Use IpMode - don't assume fixed
switch(d.ip().src_ip_mode())
{
case OstProto::Ip::e_im_fixed:
qToBigEndian((quint32) d.ip().src_ip(), buf+len);
len +=4;
qToBigEndian((quint32) d.ip().dst_ip(), buf+len);
len +=4;
break;
case OstProto::Ip::e_im_inc_host:
u = n % d.ip().src_ip_count();
subnet = d.ip().src_ip() & d.ip().src_ip_mask();
host = (((d.ip().src_ip() & ~d.ip().src_ip_mask()) + u) &
~d.ip().src_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len);
break;
case OstProto::Ip::e_im_dec_host:
u = n % d.ip().src_ip_count();
subnet = d.ip().src_ip() & d.ip().src_ip_mask();
host = (((d.ip().src_ip() & ~d.ip().src_ip_mask()) - u) &
~d.ip().src_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len);
break;
case OstProto::Ip::e_im_random_host:
subnet = d.ip().src_ip() & d.ip().src_ip_mask();
host = (qrand() & ~d.ip().src_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len);
break;
default:
qWarning("Unhandled src_ip_mode = %d", d.ip().src_ip_mode());
}
len +=4;
switch(d.ip().dst_ip_mode())
{
case OstProto::Ip::e_im_fixed:
qToBigEndian((quint32) d.ip().dst_ip(), buf+len);
break;
case OstProto::Ip::e_im_inc_host:
u = n % d.ip().dst_ip_count();
subnet = d.ip().dst_ip() & d.ip().dst_ip_mask();
host = (((d.ip().dst_ip() & ~d.ip().dst_ip_mask()) + u) &
~d.ip().dst_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len);
break;
case OstProto::Ip::e_im_dec_host:
u = n % d.ip().dst_ip_count();
subnet = d.ip().dst_ip() & d.ip().dst_ip_mask();
host = (((d.ip().dst_ip() & ~d.ip().dst_ip_mask()) - u) &
~d.ip().dst_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len);
break;
case OstProto::Ip::e_im_random_host:
subnet = d.ip().dst_ip() & d.ip().dst_ip_mask();
host = (qrand() & ~d.ip().dst_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len);
break;
default:
qWarning("Unhandled dst_ip_mode = %d", d.ip().dst_ip_mode());
}
len +=4;
// Calculate and fill in cksum (unless overridden)
if (d.ip().is_override_cksum())
qToBigEndian((quint16) d.ip().cksum(), buf+ipOfs+10);
else
*((quint16*)(buf + ipOfs + 10)) = ipv4Cksum(buf + ipOfs, len-ipOfs);
break;
}
case OstProto::StreamCore::e_l3_arp:
// TODO(LOW)
break;
@ -96,34 +304,59 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize)
case OstProto::StreamCore::e_l4_none:
break;
case OstProto::StreamCore::e_l4_tcp:
{
qToBigEndian((quint16) d.tcp().src_port(), buf+len);
len += 2;
qToBigEndian((quint16) d.tcp().dst_port(), buf+len);
len += 2;
qToBigEndian((quint16) d.tcp().seq_num(), buf+len);
len += 2;
qToBigEndian((quint16) d.tcp().ack_num(), buf+len);
len += 2;
qToBigEndian((quint32) d.tcp().seq_num(), buf+len);
len += 4;
qToBigEndian((quint32) d.tcp().ack_num(), buf+len);
len += 4;
if (d.tcp().is_override_hdrlen())
buf[len+0] = (quint8) d.tcp().hdrlen_rsvd();
else
buf[len+0] = (quint8) 0x50; // FIXME(LOW)
buf[len+1] = (quint8) d.tcp().flags();
len += 2;
qToBigEndian((quint16) d.tcp().window(), buf+len);
len +=2;
if (d.tcp().is_override_cksum())
qToBigEndian((quint16) d.tcp().cksum(), buf+len);
else
qToBigEndian((quint16) 0, buf+len); // FIXME(HI)
len +=2;
qToBigEndian((quint16) d.tcp().urg_ptr(), buf+len);
len +=2;
break;
}
case OstProto::StreamCore::e_l4_udp:
{
int udpLen = pktLen - len;
qToBigEndian((quint16) d.udp().src_port(), buf+len);
len += 2;
qToBigEndian((quint16) d.udp().dst_port(), buf+len);
len += 2;
if (d.udp().is_override_totlen())
qToBigEndian((quint16) d.udp().totlen(), buf+len);
else
qToBigEndian((quint16) udpLen, buf+len);
len +=2;
if (d.udp().is_override_cksum())
qToBigEndian((quint16) d.udp().cksum(), buf+len);
else
qToBigEndian((quint16) 0, buf+len); // FIXME(HI)
len +=2;
break;
}
case OstProto::StreamCore::e_l4_icmp:
// TODO(LOW)
break;
@ -149,6 +382,7 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize)
return pktLen;
}
//
// ------------------ PortInfo --------------------
//
@ -166,6 +400,13 @@ PortInfo::PortInfo(uint id, pcap_if_t *dev)
dev->name, pcap_geterr(devHandle));
}
#if 0
if (pcap_setdirection(devHandle, 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(devHandle, MODE_STAT)<0)
{
@ -179,10 +420,14 @@ PortInfo::PortInfo(uint id, pcap_if_t *dev)
d.set_is_oper_up(true); // FIXME(MED):check
d.set_is_exclusive_control(false); // FIXME(MED): check
memset((void*) &stats, 0, sizeof(stats));
resetStats();
// We'll create sendqueue later when required
sendQueue = NULL;
pcapExtra.sendQueueNumPkts = 0;
pcapExtra.txPkts = 0;
pcapExtra.txBytes = 0;
isSendQueueDirty=true;
// Start the monitor thread
@ -201,21 +446,47 @@ void PortInfo::update()
// TODO(LOW): calculate sendqueue size
sendQueue = pcap_sendqueue_alloc(1*MB);
pcapExtra.sendQueueNumPkts = 0;
// First sort the streams by ordinalValue
qSort(streamList);
for (int i = 0; i < streamList.size(); i++)
{
// FIXME(HI): Testing only
//if (streamList[i].d.core().is_enabled())
if (streamList[i].d.core().is_enabled())
{
pktHdr.len = streamList[i].makePacket(pktBuf, sizeof(pktBuf));
int numPackets, numBursts;
if (streamList[i].d.control().unit() ==
OstProto::StreamControl::e_su_bursts)
{
numBursts = streamList[i].d.control().num_bursts();
numPackets = streamList[i].d.control().packets_per_burst();
}
else
{
numBursts = 1;
numPackets = streamList[i].d.control().num_packets();
}
for (int j = 0; j < numBursts; j++)
{
for (int k = 0; k < numPackets; k++)
{
pktHdr.len = streamList[i].makePacket(
pktBuf, sizeof(pktBuf), j * numPackets + k);
pktHdr.caplen = pktHdr.len;
pktHdr.ts.tv_sec = pktHdr.ts.tv_usec = 0; // FIXME(HI)
if (-1 == pcap_sendqueue_queue(sendQueue, &pktHdr,
(u_char*) pktBuf))
{
qDebug("[port %d] sendqueue_queue() failed for streamidx %d\n",
id(), i);
qDebug("[port %d] sendqueue_queue() failed for "
"streamidx %d\n", id(), i);
}
else
pcapExtra.sendQueueNumPkts++;
}
}
}
}
@ -225,14 +496,29 @@ void PortInfo::update()
void PortInfo::startTransmit()
{
int n;
uint bytes;
// TODO(HI): Stream Mode - one pass/continuous
n = pcap_sendqueue_transmit(devHandle, sendQueue, false);
if (n == 0)
qDebug("port %d: send error %s\n", id(), pcap_geterr(devHandle));
bytes = pcap_sendqueue_transmit(devHandle, sendQueue, false);
if (bytes < sendQueue->len)
{
qDebug("port %d: sent (%d/%d) error %s. TxStats may be inconsistent",
id(), bytes, sendQueue->len, pcap_geterr(devHandle));
//! \TODO parse sendqueue using 'bytes' to get actual pkts sent
pcapExtra.txPkts += pcapExtra.sendQueueNumPkts;
pcapExtra.txBytes += bytes;
}
else
qDebug("port %d: sent %d bytes\n", id(), n);
{
qDebug("port %d: sent (%d/%d) bytes\n", id(), bytes, sendQueue->len);
pcapExtra.txPkts += pcapExtra.sendQueueNumPkts;
pcapExtra.txBytes += bytes;
}
// pcap_sendqueue_transmit() returned 'bytes' includes size of pcap_pkthdr
// - adjust for it
pcapExtra.txBytes -= pcapExtra.sendQueueNumPkts * sizeof(pcap_pkthdr);
}
void PortInfo::stopTransmit()
@ -241,7 +527,7 @@ void PortInfo::stopTransmit()
void PortInfo::resetStats()
{
memset((void*) &stats, 0, sizeof(stats));
memcpy((void*) &epochStats, (void*) &stats, sizeof(stats));
}
//
@ -251,21 +537,57 @@ void PortInfo::resetStats()
PortInfo::PortMonitor::PortMonitor(PortInfo *port)
{
this->port = port;
#ifdef Q_OS_WIN32
{
int sz = sizeof(PACKET_OID_DATA) + sizeof(quint64) + 4;
//oidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,
//sizeof(PACKET_OID_DATA) + sizeof(quint64) - 1);
oidData = (PPACKET_OID_DATA) malloc(sz);
if (oidData)
{
memset(oidData, 0, sz);
oidData->Length=sizeof(quint64);
}
else
qFatal("failed to alloc oidData");
}
#endif
}
void PortInfo::PortMonitor::callback(u_char *state,
const struct pcap_pkthdr *header, const u_char *pkt_data)
{
uint usec;
PortInfo *port = (PortInfo*) state;
quint64 pkts;
quint64 bytes;
// Update RxStats and RxRates using PCAP data
pkts = *((quint64*)(pkt_data + 0));
bytes = *((quint64*)(pkt_data + 8));
// 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;
port->stats.rxPkts += pkts;
port->stats.rxBytes += bytes;
// Update TxStats from PcapExtra
port->stats.txPkts = port->pcapExtra.txPkts;
port->stats.txBytes = port->pcapExtra.txBytes;
//! \TODO TxRates
// Store curr timestamp as last timestamp
port->lastTs.tv_sec = header->ts.tv_sec;
port->lastTs.tv_usec = header->ts.tv_usec;
#if 0
for (int i=0; i < 16; i++)
{
@ -276,6 +598,26 @@ void PortInfo::PortMonitor::callback(u_char *state,
qDebug("[%d: pkts : %llu]\n", port->id(), port->stats.rxPkts);
qDebug("[%d: bytes: %llu]\n", port->id(), port->stats.rxBytes);
#endif
// Retreive NIC stats
#ifdef Q_OS_WIN32
port->monitor.oidData->Oid = OID_GEN_RCV_OK;
if (PacketRequest(port->devHandle->adapter, 0, port->monitor.oidData))
{
if (port->monitor.oidData->Length <= sizeof(port->stats.txPkts))
memcpy((void*)&port->stats.rxPktsNic,
(void*)port->monitor.oidData->Data,
port->monitor.oidData->Length);
}
port->monitor.oidData->Oid = OID_GEN_XMIT_OK;
if (PacketRequest(port->devHandle->adapter, 0, port->monitor.oidData))
{
if (port->monitor.oidData->Length <= sizeof(port->stats.txPkts))
memcpy((void*)&port->stats.txPktsNic,
(void*)port->monitor.oidData->Data,
port->monitor.oidData->Length);
}
#endif
}
void PortInfo::PortMonitor::run()
@ -687,7 +1029,7 @@ const ::OstProto::PortIdList* request,
::OstProto::PortStatsList* response,
::google::protobuf::Closure* done)
{
qDebug("In %s", __PRETTY_FUNCTION__);
//qDebug("In %s", __PRETTY_FUNCTION__);
for (int i=0; i < request->port_id_size(); i++)
{
@ -701,13 +1043,25 @@ const ::OstProto::PortIdList* request,
s = response->add_port_stats();
s->mutable_port_id()->set_id(request->port_id(i).id());
s->set_rx_pkts(portInfo[portidx]->stats.rxPkts);
s->set_rx_bytes(portInfo[portidx]->stats.rxBytes);
s->set_rx_pkts(portInfo[portidx]->stats.rxPkts -
portInfo[portidx]->epochStats.rxPkts);
s->set_rx_bytes(portInfo[portidx]->stats.rxBytes -
portInfo[portidx]->epochStats.rxBytes);
s->set_rx_pkts_nic(portInfo[portidx]->stats.rxPktsNic -
portInfo[portidx]->epochStats.rxPktsNic);
s->set_rx_bytes_nic(portInfo[portidx]->stats.rxBytesNic -
portInfo[portidx]->epochStats.rxBytesNic);
s->set_rx_pps(portInfo[portidx]->stats.rxPps);
s->set_rx_bps(portInfo[portidx]->stats.rxBps);
s->set_tx_pkts(portInfo[portidx]->stats.txPkts);
s->set_tx_bytes(portInfo[portidx]->stats.txBytes);
s->set_tx_pkts(portInfo[portidx]->stats.txPkts -
portInfo[portidx]->epochStats.txPkts);
s->set_tx_bytes(portInfo[portidx]->stats.txBytes -
portInfo[portidx]->epochStats.txBytes);
s->set_tx_pkts_nic(portInfo[portidx]->stats.txPktsNic -
portInfo[portidx]->epochStats.txPktsNic);
s->set_tx_bytes_nic(portInfo[portidx]->stats.txBytesNic -
portInfo[portidx]->epochStats.txBytesNic);
s->set_tx_pps(portInfo[portidx]->stats.txPps);
s->set_tx_bps(portInfo[portidx]->stats.txBps);
}

View File

@ -16,9 +16,16 @@
#include "../rpc/pbhelper.h"
#ifdef Q_OS_WIN32
#include <packet32.h>
#endif
#define MAX_PKT_HDR_SIZE 1536
#define MAX_STREAM_NAME_SIZE 64
//! 7 byte Preamble + 1 byte SFD + 4 byte FCS
#define ETH_FRAME_HDR_SIZE 12
class MyService;
class StreamInfo
@ -29,7 +36,13 @@ class StreamInfo
OstProto::Stream d;
StreamInfo() { PbHelper pbh; pbh.ForceSetSingularDefault(&d); }
int StreamInfo::makePacket(uchar *buf, int bufMaxSize);
//quint16 ipv4Cksum(quint16 ipHdrLen, quint16 buff[]);
quint16 ipv4Cksum(uchar *buf, int len);
int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n);
public:
bool operator < (const StreamInfo &s) const
{ return(d.core().ordinal() < s.d.core().ordinal()); }
};
@ -42,6 +55,9 @@ class PortInfo
friend class PortInfo;
PortInfo *port;
#ifdef Q_OS_WIN32
PPACKET_OID_DATA oidData;
#endif
public:
PortMonitor(PortInfo *port);
static void callback(u_char *state,
@ -51,26 +67,47 @@ class PortInfo
OstProto::Port d;
pcap_if_t *dev;
pcap_t *devHandle;
pcap_send_queue *sendQueue;
bool isSendQueueDirty;
PortMonitor monitor;
struct PortStats
{
quint64 rxPkts;
quint64 rxBytes;
quint64 rxPktsNic;
quint64 rxBytesNic;
quint64 rxPps;
quint64 rxBps;
quint64 txPkts;
quint64 txBytes;
quint64 txPktsNic;
quint64 txBytesNic;
quint64 txPps;
quint64 txBps;
};
//! \todo Need lock for stats access/update
//! Stuff we need to maintain since PCAP doesn't as of now. As and when
// PCAP supports it, we'll remove from here
struct PcapExtra
{
//! pcap_sendqueue_transmit() only returns 'bytes' sent
uint sendQueueNumPkts;
//! PCAP doesn't do any tx stats
quint64 txPkts;
quint64 txBytes;
};
pcap_if_t *dev;
pcap_t *devHandle;
pcap_send_queue *sendQueue;
bool isSendQueueDirty;
PcapExtra pcapExtra;
PortMonitor monitor;
struct PortStats epochStats;
struct PortStats stats;
struct timeval lastTs; //! used for Rate Stats calculations
/*! StreamInfo::d::stream_id and index into streamList[] are NOT same! */
QList<StreamInfo> streamList;