diff --git a/client/mainwindow.cpp b/client/mainwindow.cpp index 7eef2f3..d86b01f 100644 --- a/client/mainwindow.cpp +++ b/client/mainwindow.cpp @@ -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() diff --git a/client/mainwindow.ui b/client/mainwindow.ui index 5d43edb..98ab4c2 100644 --- a/client/mainwindow.ui +++ b/client/mainwindow.ui @@ -1,159 +1,159 @@ - - MainWindow - - - - 0 - 0 - 800 - 600 - - - - MainWindow - - - - - - 0 - 0 - 800 - 21 - - - - - File - - - - - - View - - - - - - Window - - - - - - - - - - - - Help - - - - - - - - - - - - Open Config - - - - - Save Config - - - - - Save Config As ... - - - - - Open Capture - - - - - Save Capture - - - - - Save Capture As ... - - - - - E&xit - - - - - Copy Port Config - - - - - Paste Port Config - - - - - Preferences - - - - - Minimize - - - - - Maximize/Restore - - - - - Minimize All - - - - - Maximize/Restoe All - - - - - Arrange All - Cascade - - - - - Arrange All - Tile - - - - - Dock - - - - - Help - - - - - About - - - - - - + + MainWindow + + + + 0 + 0 + 800 + 650 + + + + MainWindow + + + + + + 0 + 0 + 800 + 21 + + + + + File + + + + + + View + + + + + + Window + + + + + + + + + + + + Help + + + + + + + + + + + + Open Config + + + + + Save Config + + + + + Save Config As ... + + + + + Open Capture + + + + + Save Capture + + + + + Save Capture As ... + + + + + E&xit + + + + + Copy Port Config + + + + + Paste Port Config + + + + + Preferences + + + + + Minimize + + + + + Maximize/Restore + + + + + Minimize All + + + + + Maximize/Restoe All + + + + + Arrange All - Cascade + + + + + Arrange All - Tile + + + + + Dock + + + + + Help + + + + + About + + + + + + diff --git a/client/port.cpp b/client/port.cpp index 06f40ae..3ee571e 100644 --- a/client/port.cpp +++ b/client/port.cpp @@ -20,6 +20,10 @@ Port::Port(quint32 id, quint32 portGroupId) mPortGroupId = portGroupId; } +Port::~Port() +{ +} + void Port::updatePortConfig(OstProto::Port *port) { d.MergeFrom(*port); diff --git a/client/port.h b/client/port.h index b16d680..c10eeb3 100644 --- a/client/port.h +++ b/client/port.h @@ -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; } diff --git a/client/portgroup.cpp b/client/portgroup.cpp index 70cb66e..686b436 100644 --- a/client/portgroup.cpp +++ b/client/portgroup.cpp @@ -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 portList) +void PortGroup::startTx(QList *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 { - OstProto::PortId *portId; - portId = portIdList.add_port_id(); - portId->set_id(portList.at(i)); + for (int i = 0; i < portList->size(); i++) + { + OstProto::PortId *portId; + portId = portIdList.add_port_id(); + portId->set_id(portList->at(i)); + } } serviceStub->startTx(rpcController, &portIdList, ack, NewCallback(this, &PortGroup::processStartTxAck, ack)); +_exit: + return; +} + +void PortGroup::stopTx(QList *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 *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; } diff --git a/client/portgroup.h b/client/portgroup.h index e2b5317..2ffcbaf 100644 --- a/client/portgroup.h +++ b/client/portgroup.h @@ -70,12 +70,14 @@ public: void processModifyStreamAck(OstProto::Ack *ack); - void startTx(QList portList); + void startTx(QList *portList = NULL); void processStartTxAck(OstProto::Ack *ack); + void stopTx(QList *portList = NULL); + void processStopTxAck(OstProto::Ack *ack); void getPortStats(); void processPortStatsList(OstProto::PortStatsList *portStatsList); - void clearPortStats(); + void clearPortStats(QList *portList = NULL); void processClearStatsAck(OstProto::Ack *ack); signals: diff --git a/client/portstatsfilter.ui b/client/portstatsfilter.ui index 8220436..e34fde2 100644 --- a/client/portstatsfilter.ui +++ b/client/portstatsfilter.ui @@ -5,8 +5,8 @@ 0 0 - 402 - 275 + 588 + 298 @@ -71,8 +71,55 @@ QAbstractItemView::ExtendedSelection + + QListView::Free + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + U + + + + + + + D + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + diff --git a/client/portstatsmodel.cpp b/client/portstatsmodel.cpp index d8b40e6..b3fae30 100644 --- a/client/portstatsmodel.cpp +++ b/client/portstatsmodel.cpp @@ -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 &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); } diff --git a/client/portstatsmodel.h b/client/portstatsmodel.h index 6dc4693..1825524 100644 --- a/client/portstatsmodel.h +++ b/client/portstatsmodel.h @@ -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 portList; }; diff --git a/client/portstatswindow.cpp b/client/portstatswindow.cpp index 28b8f88..5f4ff6b 100644 --- a/client/portstatswindow.cpp +++ b/client/portstatswindow.cpp @@ -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 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 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 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 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() diff --git a/client/portstatswindow.h b/client/portstatswindow.h index 98642c1..c1d581f 100644 --- a/client/portstatswindow.h +++ b/client/portstatswindow.h @@ -5,6 +5,7 @@ #include #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(); diff --git a/client/portswindow.cpp b/client/portswindow.cpp index f711f55..645bd1b 100644 --- a/client/portswindow.cpp +++ b/client/portswindow.cpp @@ -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() diff --git a/client/stream.cpp b/client/stream.cpp index 653859c..2d82040 100644 --- a/client/stream.cpp +++ b/client/stream.cpp @@ -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 diff --git a/client/stream.h b/client/stream.h index 9500064..42f74ff 100644 --- a/client/stream.h +++ b/client/stream.h @@ -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 diff --git a/client/streamconfigdialog.cpp b/client/streamconfigdialog.cpp index 0202825..cef9771 100644 --- a/client/streamconfigdialog.cpp +++ b/client/streamconfigdialog.cpp @@ -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() diff --git a/client/streamconfigdialog.h b/client/streamconfigdialog.h index 2485011..f95205d 100644 --- a/client/streamconfigdialog.h +++ b/client/streamconfigdialog.h @@ -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); diff --git a/client/streamconfigdialog.ui b/client/streamconfigdialog.ui index 503eb27..f3ed791 100644 --- a/client/streamconfigdialog.ui +++ b/client/streamconfigdialog.ui @@ -33,7 +33,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff - 2 + 0 @@ -214,7 +214,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff None - false + true @@ -241,7 +241,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff 802.3 LLC - true + false @@ -332,7 +332,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff - + Type @@ -420,7 +420,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff - false + true ICMP @@ -430,7 +430,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff - false + true IGMP @@ -440,7 +440,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff - false + true TCP @@ -450,7 +450,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff - false + true UDP @@ -2151,12 +2151,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 252 - 288 + 112 + 267 - 252 - 317 + 112 + 267 @@ -2167,12 +2167,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 252 - 388 + 112 + 267 - 252 - 417 + 112 + 267 @@ -2183,12 +2183,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 31 - 259 + 92 + 267 - 41 - 317 + 92 + 267 @@ -2199,12 +2199,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 31 - 259 + 92 + 267 - 81 - 317 + 92 + 267 @@ -2215,12 +2215,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 31 - 259 + 92 + 267 - 120 - 317 + 92 + 267 @@ -2231,12 +2231,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 31 - 259 + 92 + 267 - 252 - 288 + 112 + 267 @@ -2247,12 +2247,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 31 - 359 + 92 + 267 - 41 - 417 + 92 + 267 @@ -2263,12 +2263,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 31 - 359 + 92 + 267 - 120 - 417 + 92 + 267 @@ -2279,12 +2279,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 31 - 359 + 92 + 267 - 252 - 388 + 112 + 267 @@ -2295,12 +2295,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 31 - 359 + 92 + 267 - 81 - 417 + 92 + 267 @@ -2311,12 +2311,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 123 - 305 + 145 + 334 - 123 - 305 + 145 + 334 @@ -2327,12 +2327,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 123 - 305 + 145 + 334 - 123 - 305 + 145 + 334 @@ -2343,12 +2343,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 42 - 171 + 123 + 305 - 232 - 170 + 123 + 305 @@ -2359,12 +2359,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 42 - 197 + 123 + 305 - 232 - 196 + 123 + 305 @@ -2375,12 +2375,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 42 - 252 + 123 + 305 - 232 - 251 + 123 + 305 @@ -2391,12 +2391,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 383 - 274 + 192 + 305 - 506 - 274 + 192 + 305 @@ -2407,12 +2407,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 123 - 305 + 145 + 334 - 123 - 305 + 145 + 334 @@ -2423,492 +2423,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 123 - 305 + 145 + 334 - 123 - 305 - - - - - rbFtNone - toggled(bool) - lblDsap - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFtNone - toggled(bool) - leDsap - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtNone - toggled(bool) - lblSsap - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFtNone - toggled(bool) - leSsap - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtNone - toggled(bool) - lblControl - setHidden(bool) - - - 57 - 218 - - - 137 - 237 - - - - - rbFtNone - toggled(bool) - leControl - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtNone - toggled(bool) - lblOui - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFtNone - toggled(bool) - leOui - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtNone - toggled(bool) - lblTpe - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFtNone - toggled(bool) - leType - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtEthernet2 - toggled(bool) - lblDsap - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFtEthernet2 - toggled(bool) - leDsap - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtEthernet2 - toggled(bool) - lblSsap - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFtEthernet2 - toggled(bool) - leSsap - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - lblControl - setHidden(bool) - - - 57 - 218 - - - 137 - 237 - - - - - rbFt802Dot3Raw - toggled(bool) - leControl - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtEthernet2 - toggled(bool) - lblControl - setHidden(bool) - - - 57 - 218 - - - 137 - 237 - - - - - rbFtEthernet2 - toggled(bool) - leControl - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtEthernet2 - toggled(bool) - lblOui - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFtEthernet2 - toggled(bool) - leOui - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - lblDsap - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - leDsap - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - lblSsap - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - leSsap - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - lblControl - setHidden(bool) - - - 57 - 218 - - - 137 - 237 - - - - - rbFt802Dot3Raw - toggled(bool) - leControl - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - lblOui - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - leOui - setHidden(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - lblTpe - setHidden(bool) - - - 57 - 218 - - - 58 - 218 - - - - - rbFt802Dot3Raw - toggled(bool) - leType - setHidden(bool) - - - 57 - 218 - - - 99 - 218 + 145 + 334 @@ -2944,182 +2464,6 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff - - rbFtLlcSnap - toggled(bool) - leDsap - setDisabled(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtLlcSnap - toggled(bool) - leSsap - setDisabled(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbFtLlcSnap - toggled(bool) - leControl - setDisabled(bool) - - - 57 - 218 - - - 99 - 218 - - - - - rbL3Ipv4 - toggled(bool) - rbL4Tcp - setEnabled(bool) - - - 570 - 218 - - - 570 - 302 - - - - - rbL3Ipv4 - toggled(bool) - rbL4Udp - setEnabled(bool) - - - 570 - 218 - - - 570 - 302 - - - - - rbL3Ipv4 - toggled(bool) - rbL4Other - setEnabled(bool) - - - 570 - 218 - - - 570 - 302 - - - - - rbL3Ipv4 - toggled(bool) - rbL4Icmp - setEnabled(bool) - - - 570 - 218 - - - 570 - 302 - - - - - rbL3Ipv4 - toggled(bool) - rbL4Igmp - setEnabled(bool) - - - 570 - 218 - - - 570 - 302 - - - - - rbL3None - clicked() - rbL4None - click() - - - 570 - 218 - - - 570 - 302 - - - - - rbL3Arp - clicked() - rbL4None - click() - - - 570 - 218 - - - 570 - 302 - - - - - rbL3Other - clicked() - rbL4None - click() - - - 570 - 218 - - - 570 - 302 - - - rbActionGotoStream toggled(bool) @@ -3127,12 +2471,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 381 - 140 + 136 + 120 - 381 - 174 + 136 + 120 @@ -3143,12 +2487,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 30 - 69 + 41 + 101 - 85 - 285 + 96 + 120 @@ -3159,12 +2503,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 30 - 94 + 41 + 120 - 67 - 331 + 78 + 120 @@ -3175,12 +2519,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff setEnabled(bool) - 30 - 94 + 41 + 120 - 222 - 189 + 136 + 120 diff --git a/client/streammodel.cpp b/client/streammodel.cpp index 3ee9136..32dce31 100644 --- a/client/streammodel.cpp +++ b/client/streammodel.cpp @@ -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: diff --git a/common/protocol.proto b/common/protocol.proto index 7ffd54f..fee57b9 100644 --- a/common/protocol.proto +++ b/common/protocol.proto @@ -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 { diff --git a/rpc/pbrpcchannel.cpp b/rpc/pbrpcchannel.cpp index 366ca6f..ed60d2f 100644 --- a/rpc/pbrpcchannel.cpp +++ b/rpc/pbrpcchannel.cpp @@ -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 - qDebug("client(%s) sending %d bytes encoding <%s>", __FUNCTION__, len+8, - req->DebugString().c_str()); - BUFDUMP(msg, len+8); + // 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); - qDebug("client(%s): Parsed as %s", __FUNCTION__, - response->DebugString().c_str()); + + // Avoid printing stats + if (method != 12) + { + qDebug("client(%s): Parsed as %s", __FUNCTION__, + response->DebugString().c_str()); + } if (!response->IsInitialized()) { diff --git a/rpc/rpcserver.cpp b/rpc/rpcserver.cpp index 7b6335b..a3978cb 100644 --- a/rpc/rpcserver.cpp +++ b/rpc/rpcserver.cpp @@ -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 - qDebug("Server(%s): sending %d bytes to client encoding <%s>", - __FUNCTION__, len + 8, resp->DebugString().c_str()); - //BUFDUMP(msg, len + 8); + // 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)); diff --git a/server/drone.pro b/server/drone.pro index 79cbd1a..3642823 100644 --- a/server/drone.pro +++ b/server/drone.pro @@ -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 diff --git a/server/myservice.cpp b/server/myservice.cpp index 79db27b..b21310d 100644 --- a/server/myservice.cpp +++ b/server/myservice.cpp @@ -1,30 +1,177 @@ #include "myservice.h" #include "qdebug.h" +#include #include +#ifdef Q_OS_WIN32 +#include +#include +#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 - qToBigEndian((quint64) d.mac().dst_mac(), scratch); + 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; - qToBigEndian((quint64) d.mac().src_mac(), scratch); - memcpy((buf + len), &scratch + 2, 6); + + switch (d.mac().src_mac_mode()) + { + case OstProto::Mac::e_mm_fixed: + qToBigEndian((quint64) d.mac().src_mac(), scratch); + 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; - qToBigEndian((quint16) d.ip().tot_len(), buf+len); + + 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 - qToBigEndian((quint32) d.ip().src_ip(), buf+len); + switch(d.ip().src_ip_mode()) + { + case OstProto::Ip::e_im_fixed: + qToBigEndian((quint32) d.ip().src_ip(), buf+len); + 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; - qToBigEndian((quint32) d.ip().dst_ip(), buf+len); + + 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; - buf[len+0] = (quint8) d.tcp().hdrlen_rsvd(); + + 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; - qToBigEndian((quint16) d.tcp().cksum(), buf+len); + + 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; - qToBigEndian((quint16) d.udp().totlen(), buf+len); + + if (d.udp().is_override_totlen()) + qToBigEndian((quint16) d.udp().totlen(), buf+len); + else + qToBigEndian((quint16) udpLen, buf+len); len +=2; - qToBigEndian((quint16) d.udp().cksum(), buf+len); + + 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)); - pktHdr.caplen = pktHdr.len; - pktHdr.ts.tv_sec = pktHdr.ts.tv_usec = 0; // FIXME(HI) + int numPackets, numBursts; - if (-1 == pcap_sendqueue_queue(sendQueue, &pktHdr, - (u_char*) pktBuf)) + if (streamList[i].d.control().unit() == + OstProto::StreamControl::e_su_bursts) { - qDebug("[port %d] sendqueue_queue() failed for streamidx %d\n", - id(), i); + 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); + } + 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; - pkts = *((quint64*)(pkt_data + 0)); - bytes = *((quint64*)(pkt_data + 8)); + // 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); } diff --git a/server/myservice.h b/server/myservice.h index 69e2f71..ecb474e 100644 --- a/server/myservice.h +++ b/server/myservice.h @@ -16,9 +16,16 @@ #include "../rpc/pbhelper.h" +#ifdef Q_OS_WIN32 +#include +#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()); } }; @@ -41,7 +54,10 @@ class PortInfo { friend class PortInfo; - PortInfo *port; + 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 streamList;