Tcp/Udp checksums done.

Frame Length Modes done.
Data Pattern Modes done.
Some minor fixes/enhancements in streamconfigdialog.
Added a "Edit Stream" action in StreamList context menu
This commit is contained in:
Srivats P. 2008-10-05 17:07:33 +00:00
parent 62a82dfb80
commit bfc0e8d4c8
12 changed files with 478 additions and 192 deletions

View File

@ -159,6 +159,7 @@ void PortGroup::when_configApply(int portIndex, uint *cookie)
case 3: case 3:
qDebug("apply completed"); qDebug("apply completed");
mPorts[portIndex].when_syncComplete();
delete cookie; delete cookie;
break; break;

View File

@ -12,7 +12,7 @@ PortStatsModel::PortStatsModel(PortGroupList *p, QObject *parent)
timer = new QTimer(); timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(updateStats())); connect(timer, SIGNAL(timeout()), this, SLOT(updateStats()));
timer->start(5000); timer->start(2000);
} }
int PortStatsModel::rowCount(const QModelIndex &parent) const int PortStatsModel::rowCount(const QModelIndex &parent) const

View File

@ -23,6 +23,7 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
tvPortList->addAction(actionDisconnect_Port_Group); tvPortList->addAction(actionDisconnect_Port_Group);
tvStreamList->addAction(actionNew_Stream); tvStreamList->addAction(actionNew_Stream);
tvStreamList->addAction(actionEdit_Stream);
tvStreamList->addAction(actionDelete_Stream); tvStreamList->addAction(actionDelete_Stream);
tvStreamList->setModel(plm->getStreamModel()); tvStreamList->setModel(plm->getStreamModel());
@ -32,10 +33,12 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(when_portModel_dataChanged(const QModelIndex&, this, SLOT(when_portModel_dataChanged(const QModelIndex&,
const QModelIndex&))); const QModelIndex&)));
connect( tvPortList->selectionModel(), connect( tvPortList->selectionModel(),
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(when_portView_currentChanged(const QModelIndex&, this, SLOT(when_portView_currentChanged(const QModelIndex&,
const QModelIndex&))); const QModelIndex&)));
connect( tvStreamList->selectionModel(), connect( tvStreamList->selectionModel(),
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(when_streamView_currentChanged(const QModelIndex&, this, SLOT(when_streamView_currentChanged(const QModelIndex&,
@ -43,13 +46,16 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
connect( tvStreamList->selectionModel(), connect( tvStreamList->selectionModel(),
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
this, SLOT(when_streamView_selectionChanged())); this, SLOT(when_streamView_selectionChanged()));
#if 0
connect( tvPortList->selectionModel(), connect( tvPortList->selectionModel(),
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
plm->getStreamModel(), SLOT(setCurrentPortIndex(const QModelIndex&))); plm->getStreamModel(), SLOT(setCurrentPortIndex(const QModelIndex&)));
#endif
// Initially we don't have any ports - so trigger selection of // Initially we don't have any ports/streams - so send signal triggers
// portgroup detail page
when_portView_currentChanged(QModelIndex(), QModelIndex()); when_portView_currentChanged(QModelIndex(), QModelIndex());
when_streamView_currentChanged(QModelIndex(), QModelIndex());
} }
PortsWindow::~PortsWindow() PortsWindow::~PortsWindow()
@ -66,11 +72,6 @@ void PortsWindow::on_tvStreamList_activated(const QModelIndex & index)
qDebug("%s: invalid index", __FUNCTION__); qDebug("%s: invalid index", __FUNCTION__);
return; return;
} }
#if 0 // CleanedUp!
// FIXME(MED): This way of passing params must be changed
scd = new StreamConfigDialog(plm->getStreamModel()->currentPortStreamList(),
(uint) index.row(), this);
#endif
scd = new StreamConfigDialog(plm->port(tvPortList->currentIndex()), scd = new StreamConfigDialog(plm->port(tvPortList->currentIndex()),
index.row(), this); index.row(), this);
qDebug("stream list activated\n"); qDebug("stream list activated\n");
@ -81,7 +82,9 @@ void PortsWindow::on_tvStreamList_activated(const QModelIndex & index)
void PortsWindow::when_portView_currentChanged(const QModelIndex& current, void PortsWindow::when_portView_currentChanged(const QModelIndex& current,
const QModelIndex& previous) const QModelIndex& previous)
{ {
plm->getStreamModel()->setCurrentPortIndex(current);
updatePortViewActions(current); updatePortViewActions(current);
updateStreamViewActions();
if (!current.isValid()) if (!current.isValid())
{ {
@ -143,16 +146,32 @@ void PortsWindow::updateStreamViewActions(const QModelIndex& current)
void PortsWindow::updateStreamViewActions() void PortsWindow::updateStreamViewActions()
{ {
if (tvStreamList->selectionModel()->hasSelection()) // For some reason hasSelection() returns true even if selection size is 0
// so additional check for size introduced
if (tvStreamList->selectionModel()->hasSelection() &&
(tvStreamList->selectionModel()->selection().size() > 0))
{ {
qDebug("Has selection %d", qDebug("Has selection %d",
tvStreamList->selectionModel()->selection().size()); tvStreamList->selectionModel()->selection().size());
// If more than one non-contiguous ranges selected, disable "New"
// If more than one non-contiguous ranges selected,
// disable "New" and "Edit"
if (tvStreamList->selectionModel()->selection().size() > 1) if (tvStreamList->selectionModel()->selection().size() > 1)
{
actionNew_Stream->setDisabled(true); actionNew_Stream->setDisabled(true);
actionEdit_Stream->setDisabled(true);
}
else else
{
actionNew_Stream->setEnabled(true); actionNew_Stream->setEnabled(true);
// Enable "Edit" only if the single range has a single row
if (tvStreamList->selectionModel()->selection().at(0).height() > 1)
actionEdit_Stream->setDisabled(true);
else
actionEdit_Stream->setEnabled(true);
}
// Delete is always enabled as long as we have a selection // Delete is always enabled as long as we have a selection
actionDelete_Stream->setEnabled(true); actionDelete_Stream->setEnabled(true);
} }
@ -160,6 +179,7 @@ void PortsWindow::updateStreamViewActions()
{ {
qDebug("No selection"); qDebug("No selection");
actionNew_Stream->setEnabled(true); actionNew_Stream->setEnabled(true);
actionEdit_Stream->setDisabled(true);
actionDelete_Stream->setDisabled(true); actionDelete_Stream->setDisabled(true);
} }
} }
@ -346,6 +366,19 @@ void PortsWindow::on_actionNew_Stream_triggered()
plm->getStreamModel()->insertRows(row, count); plm->getStreamModel()->insertRows(row, count);
} }
void PortsWindow::on_actionEdit_Stream_triggered()
{
qDebug("Edit Stream Action");
// Ensure we have only one range selected which contains only one row
if ((tvStreamList->selectionModel()->selection().size() == 1) &&
(tvStreamList->selectionModel()->selection().at(0).height() == 1))
{
on_tvStreamList_activated(tvStreamList->selectionModel()->
selection().at(0).topLeft());
}
}
void PortsWindow::on_actionDelete_Stream_triggered() void PortsWindow::on_actionDelete_Stream_triggered()
{ {
qDebug("Delete Stream Action"); qDebug("Delete Stream Action");

View File

@ -49,6 +49,7 @@ private slots:
void on_actionDisconnect_Port_Group_triggered(); void on_actionDisconnect_Port_Group_triggered();
void on_actionNew_Stream_triggered(); void on_actionNew_Stream_triggered();
void on_actionEdit_Stream_triggered();
void on_actionDelete_Stream_triggered(); void on_actionDelete_Stream_triggered();
}; };

View File

@ -206,6 +206,14 @@
<string>Delete Stream</string> <string>Delete Stream</string>
</property> </property>
</action> </action>
<action name="actionEdit_Stream" >
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/stream_edit.png</iconset>
</property>
<property name="text" >
<string>Edit Stream</string>
</property>
</action>
</widget> </widget>
<resources> <resources>
<include location="ostinato.qrc" /> <include location="ostinato.qrc" />

View File

@ -883,9 +883,9 @@ public:
}; };
enum DataPatternMode { enum DataPatternMode {
e_dp_fixed, e_dp_fixed_word,
e_dp_inc, e_dp_inc_byte,
e_dp_dec, e_dp_dec_byte,
e_dp_random e_dp_random
}; };

View File

@ -12,6 +12,8 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
{ {
setupUi(this); setupUi(this);
setupUiExtra(); setupUiExtra();
// setupUi
// Time to play match the signals and slots! // Time to play match the signals and slots!
connect(rbFtNone, SIGNAL(toggled(bool)), rbL3None, SLOT(setChecked(bool))); connect(rbFtNone, SIGNAL(toggled(bool)), rbL3None, SLOT(setChecked(bool)));
@ -28,6 +30,11 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
connect(rbFtNone, SIGNAL(toggled(bool)), lblType, SLOT(setHidden(bool))); connect(rbFtNone, SIGNAL(toggled(bool)), lblType, SLOT(setHidden(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), leType, SLOT(setHidden(bool))); connect(rbFtNone, SIGNAL(toggled(bool)), leType, SLOT(setHidden(bool)));
// Enable/Disable L3 Protocol Choices for FT None
connect(rbFtNone, SIGNAL(toggled(bool)), rbL3None, SLOT(setEnabled(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), rbL3Ipv4, SLOT(setDisabled(bool)));
connect(rbFtNone, SIGNAL(toggled(bool)), rbL3Arp, SLOT(setDisabled(bool)));
// Show/Hide FrameType related inputs for FT Ethernet2 // Show/Hide FrameType related inputs for FT Ethernet2
connect(rbFtEthernet2, SIGNAL(toggled(bool)), lblDsap, SLOT(setHidden(bool))); connect(rbFtEthernet2, SIGNAL(toggled(bool)), lblDsap, SLOT(setHidden(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), leDsap, SLOT(setHidden(bool))); connect(rbFtEthernet2, SIGNAL(toggled(bool)), leDsap, SLOT(setHidden(bool)));
@ -40,6 +47,11 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
connect(rbFtEthernet2, SIGNAL(toggled(bool)), lblType, SLOT(setVisible(bool))); connect(rbFtEthernet2, SIGNAL(toggled(bool)), lblType, SLOT(setVisible(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), leType, SLOT(setVisible(bool))); connect(rbFtEthernet2, SIGNAL(toggled(bool)), leType, SLOT(setVisible(bool)));
// Enable/Disable L3 Protocol Choices for FT Ethernet2
connect(rbFtEthernet2, SIGNAL(toggled(bool)), rbL3None, SLOT(setEnabled(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), rbL3Ipv4, SLOT(setEnabled(bool)));
connect(rbFtEthernet2, SIGNAL(toggled(bool)), rbL3Arp, SLOT(setEnabled(bool)));
// Show/Hide FrameType related inputs for FT 802.3 Raw // Show/Hide FrameType related inputs for FT 802.3 Raw
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), lblDsap, SLOT(setHidden(bool))); connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), lblDsap, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), leDsap, SLOT(setHidden(bool))); connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), leDsap, SLOT(setHidden(bool)));
@ -52,6 +64,14 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), lblType, SLOT(setHidden(bool))); connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), lblType, SLOT(setHidden(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), leType, SLOT(setHidden(bool))); connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), leType, SLOT(setHidden(bool)));
// Force L3 = None if FT = 802.3 Raw
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), rbL3None, SLOT(setChecked(bool)));
// Enable/Disable L3 Protocol Choices for FT 802Dot3Raw
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), rbL3None, SLOT(setEnabled(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), rbL3Ipv4, SLOT(setDisabled(bool)));
connect(rbFt802Dot3Raw, SIGNAL(toggled(bool)), rbL3Arp, SLOT(setDisabled(bool)));
// Show/Hide FrameType related inputs for FT 802.3 LLC // Show/Hide FrameType related inputs for FT 802.3 LLC
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), lblDsap, SLOT(setVisible(bool))); connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), lblDsap, SLOT(setVisible(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), leDsap, SLOT(setVisible(bool))); connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), leDsap, SLOT(setVisible(bool)));
@ -64,6 +84,14 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), lblType, SLOT(setHidden(bool))); connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), lblType, SLOT(setHidden(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), leType, SLOT(setHidden(bool))); connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), leType, SLOT(setHidden(bool)));
// Force L3 = None if FT = 802.3 LLC (to ensure a valid L3 is selected)
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), rbL3None, SLOT(setChecked(bool)));
// Enable/Disable L3 Protocol Choices for FT 802Dot3Llc
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), rbL3None, SLOT(setEnabled(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), rbL3Ipv4, SLOT(setEnabled(bool)));
connect(rbFt802Dot3Llc, SIGNAL(toggled(bool)), rbL3Arp, SLOT(setDisabled(bool)));
// Show/Hide FrameType related inputs for FT 802.3 LLC SNAP // 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)), lblDsap, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leDsap, SLOT(setVisible(bool))); connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leDsap, SLOT(setVisible(bool)));
@ -76,6 +104,11 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblType, SLOT(setVisible(bool))); connect(rbFtLlcSnap, SIGNAL(toggled(bool)), lblType, SLOT(setVisible(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leType, SLOT(setVisible(bool))); connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leType, SLOT(setVisible(bool)));
// Enable/Disable L3 Protocol Choices for FT 802.3 LLC SNAP
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), rbL3None, SLOT(setEnabled(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), rbL3Ipv4, SLOT(setEnabled(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), rbL3Arp, SLOT(setEnabled(bool)));
// Enable/Disable FrameType related inputs for FT 802.3 LLC SNAP // 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)), lblDsap, SLOT(setDisabled(bool)));
connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leDsap, SLOT(setDisabled(bool))); connect(rbFtLlcSnap, SIGNAL(toggled(bool)), leDsap, SLOT(setDisabled(bool)));
@ -90,7 +123,6 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
connect(rbL3None, SIGNAL(toggled(bool)), rbL4Igmp, 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)), rbL4Tcp, SLOT(setDisabled(bool)));
connect(rbL3None, SIGNAL(toggled(bool)), rbL4Udp, 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 // Force L4 Protocol = None if L3 Protocol is set to None
connect(rbL3None, SIGNAL(toggled(bool)), rbL4None, SLOT(setChecked(bool))); connect(rbL3None, SIGNAL(toggled(bool)), rbL4None, SLOT(setChecked(bool)));
@ -101,7 +133,6 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
connect(rbL3Ipv4, SIGNAL(toggled(bool)), rbL4Igmp, 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)), rbL4Tcp, SLOT(setEnabled(bool)));
connect(rbL3Ipv4, SIGNAL(toggled(bool)), rbL4Udp, 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 // Enable/Disable L4 Protocol Choices for L3 Protocol ARP
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4None, SLOT(setEnabled(bool))); connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4None, SLOT(setEnabled(bool)));
@ -109,15 +140,20 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4Igmp, 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)), rbL4Tcp, SLOT(setDisabled(bool)));
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4Udp, 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 // Force L4 Protocol = None if L3 Protocol is set to ARP
connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4None, SLOT(setChecked(bool))); connect(rbL3Arp, SIGNAL(toggled(bool)), rbL4None, SLOT(setChecked(bool)));
// Init with FT=Eth2 to trigger signals; actual value will be //TODO: remove if not needed
// initialized by LoadCurrentStream() #if 0
// This set of 'clicks' is a hack to trigger signals at dialog creation
// time so that a coherent 'set' is initialized
// Actual stream values will be initialized by LoadCurrentStream()
rbL3Ipv4->click();
rbL3None->click();
rbFtEthernet2->click(); rbFtEthernet2->click();
rbFtNone->click(); rbFtNone->click();
#endif
//mpStreamList = streamList; //mpStreamList = streamList;
mCurrentStreamIndex = streamIndex; mCurrentStreamIndex = streamIndex;
@ -148,7 +184,21 @@ void StreamConfigDialog::setupUiExtra()
QRegExp reHex4B("[0-9,a-f,A-F]{1,8}"); QRegExp reHex4B("[0-9,a-f,A-F]{1,8}");
QRegExp reMac("([0-9,a-f,A-F]{2,2}[:-]){5,5}[0-9,a-f,A-F]{2,2}"); QRegExp reMac("([0-9,a-f,A-F]{2,2}[:-]){5,5}[0-9,a-f,A-F]{2,2}");
// Setup default stuff that cannot be done in designer // ---- Setup default stuff that cannot be done in designer ----
// Since the dialog defaults are FT = None, L3 = None, L4 = None;
// hide associated input fields since it can't be done in Designer
lblDsap->setHidden(true);
leDsap->setHidden(true);
lblSsap->setHidden(true);
leSsap->setHidden(true);
lblControl->setHidden(true);
leControl->setHidden(true);
lblOui->setHidden(true);
leOui->setHidden(true);
lblType->setHidden(true);
leType->setHidden(true);
twProto->setTabEnabled(2, FALSE); twProto->setTabEnabled(2, FALSE);
twProto->setTabEnabled(3, FALSE); twProto->setTabEnabled(3, FALSE);
@ -189,17 +239,73 @@ StreamConfigDialog::~StreamConfigDialog()
delete mpPacketModel; delete mpPacketModel;
} }
void StreamConfigDialog::on_cmbPatternMode_currentIndexChanged(QString mode)
{
if (mode == "Fixed Word")
{
lePattern->setEnabled(true);
}
else if (mode == "Increment Byte")
{
lePattern->setDisabled(true);
}
else if (mode == "Decrement Byte")
{
lePattern->setDisabled(true);
}
if (mode == "Random")
{
lePattern->setDisabled(true);
}
else
{
qWarning("Unhandled/Unknown PatternMode = %s", mode.toAscii().data());
}
}
void StreamConfigDialog::on_cmbPktLenMode_currentIndexChanged(QString mode)
{
if (mode == "Fixed")
{
lePktLen->setEnabled(true);
lePktLenMin->setDisabled(true);
lePktLenMax->setDisabled(true);
}
else if (mode == "Increment")
{
lePktLen->setDisabled(true);
lePktLenMin->setEnabled(true);
lePktLenMax->setEnabled(true);
}
else if (mode == "Decrement")
{
lePktLen->setDisabled(true);
lePktLenMin->setEnabled(true);
lePktLenMax->setEnabled(true);
}
else if (mode == "Random")
{
lePktLen->setDisabled(true);
lePktLenMin->setEnabled(true);
lePktLenMax->setEnabled(true);
}
else
{
qWarning("Unhandled/Unknown PktLenMode = %s", mode.toAscii().data());
}
}
void StreamConfigDialog::on_cmbDstMacMode_currentIndexChanged(QString mode) void StreamConfigDialog::on_cmbDstMacMode_currentIndexChanged(QString mode)
{ {
if (mode == "Fixed") if (mode == "Fixed")
{ {
leDstMacCount->setEnabled(FALSE); leDstMacCount->setEnabled(false);
leDstMacStep->setEnabled(FALSE); leDstMacStep->setEnabled(false);
} }
else else
{ {
leDstMacCount->setEnabled(TRUE); leDstMacCount->setEnabled(true);
leDstMacStep->setEnabled(TRUE); leDstMacStep->setEnabled(true);
} }
} }
@ -207,13 +313,41 @@ void StreamConfigDialog::on_cmbSrcMacMode_currentIndexChanged(QString mode)
{ {
if (mode == "Fixed") if (mode == "Fixed")
{ {
leSrcMacCount->setEnabled(FALSE); leSrcMacCount->setEnabled(false);
leSrcMacStep->setEnabled(FALSE); leSrcMacStep->setEnabled(false);
} }
else else
{ {
leSrcMacCount->setEnabled(TRUE); leSrcMacCount->setEnabled(true);
leSrcMacStep->setEnabled(TRUE); leSrcMacStep->setEnabled(true);
}
}
void StreamConfigDialog::on_cmbIpSrcAddrMode_currentIndexChanged(QString mode)
{
if (mode == "Fixed")
{
leIpSrcAddrCount->setDisabled(true);
leIpSrcAddrMask->setDisabled(true);
}
else
{
leIpSrcAddrCount->setEnabled(true);
leIpSrcAddrMask->setEnabled(true);
}
}
void StreamConfigDialog::on_cmbIpDstAddrMode_currentIndexChanged(QString mode)
{
if (mode == "Fixed")
{
leIpDstAddrCount->setDisabled(true);
leIpDstAddrMask->setDisabled(true);
}
else
{
leIpDstAddrCount->setEnabled(true);
leIpDstAddrMask->setEnabled(true);
} }
} }
@ -371,14 +505,6 @@ void StreamConfigDialog::on_rbL4Udp_toggled(bool checked)
} }
} }
void StreamConfigDialog::on_rbL4Other_toggled(bool checked)
{
if (checked)
leIpProto->setEnabled(true);
else
leIpProto->setEnabled(false);
}
void StreamConfigDialog::update_NumPacketsAndNumBursts() void StreamConfigDialog::update_NumPacketsAndNumBursts()
{ {
if (rbSendPackets->isChecked() && rbModeFixed->isChecked()) if (rbSendPackets->isChecked() && rbModeFixed->isChecked())
@ -512,32 +638,6 @@ void StreamConfigDialog::LoadCurrentStream()
qDebug("%s: unknown l4 Protocol %d", __FUNCTION__, qDebug("%s: unknown l4 Protocol %d", __FUNCTION__,
pStream->l4Proto()); pStream->l4Proto());
} }
// PB (not needed anymore?)
#if 0
// Check for specific supported protocols first ...
if (pStream->eth2()->type() == ETH_TYP_IP)
rbL3Ipv4->setChecked(TRUE);
else if (pStream->eth2()->type() == ETH_TYP_ARP)
rbL3Arp->setChecked(TRUE);
// ... then for None/Other
rbL3None->setChecked((pStream->proto.protoMask & PM_L3_PROTO_NONE) > 0);
rbL3Other->setChecked((pStream->proto.protoMask & PM_L3_PROTO_OTHER) > 0);
// Check for specific supported protocols first ...
if (pStream->proto.ipProto == IP_PROTO_ICMP)
rbL4Icmp->setChecked(TRUE);
else if (pStream->proto.ipProto == IP_PROTO_IGMP)
rbL4Igmp->setChecked(TRUE);
else if (pStream->proto.ipProto == IP_PROTO_TCP)
rbL4Tcp->setChecked(TRUE);
else if (pStream->proto.ipProto == IP_PROTO_UDP)
rbL4Udp->setChecked(TRUE);
// ... then for None/Other
rbL4None->setChecked((pStream->proto.protoMask & PM_L4_PROTO_NONE) > 0);
rbL4Other->setChecked((pStream->proto.protoMask & PM_L4_PROTO_OTHER) > 0);
#endif
} }
// L2 // L2

View File

@ -39,8 +39,12 @@ private:
void StoreCurrentStream(); void StoreCurrentStream();
private slots: private slots:
void on_cmbPatternMode_currentIndexChanged(QString mode);
void on_cmbPktLenMode_currentIndexChanged(QString mode);
void on_cmbDstMacMode_currentIndexChanged(QString mode); void on_cmbDstMacMode_currentIndexChanged(QString mode);
void on_cmbSrcMacMode_currentIndexChanged(QString mode); void on_cmbSrcMacMode_currentIndexChanged(QString mode);
void on_cmbIpSrcAddrMode_currentIndexChanged(QString mode);
void on_cmbIpDstAddrMode_currentIndexChanged(QString mode);
void on_pbPrev_clicked(); void on_pbPrev_clicked();
void on_pbNext_clicked(); void on_pbNext_clicked();
@ -57,7 +61,6 @@ private slots:
void on_rbL4Igmp_toggled(bool checked); void on_rbL4Igmp_toggled(bool checked);
void on_rbL4Tcp_toggled(bool checked); void on_rbL4Tcp_toggled(bool checked);
void on_rbL4Udp_toggled(bool checked); void on_rbL4Udp_toggled(bool checked);
void on_rbL4Other_toggled(bool checked);
void update_NumPacketsAndNumBursts(); void update_NumPacketsAndNumBursts();

View File

@ -8,7 +8,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>554</width> <width>534</width>
<height>521</height> <height>521</height>
</rect> </rect>
</property> </property>
@ -63,17 +63,17 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
<widget class="QComboBox" name="cmbPatternMode" > <widget class="QComboBox" name="cmbPatternMode" >
<item> <item>
<property name="text" > <property name="text" >
<string>Fixed</string> <string>Fixed Word</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text" > <property name="text" >
<string>Increment</string> <string>Increment Byte</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text" > <property name="text" >
<string>Decrement</string> <string>Decrement Byte</string>
</property> </property>
</item> </item>
<item> <item>
@ -141,6 +141,9 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
<item row="0" column="2" > <item row="0" column="2" >
<widget class="QLineEdit" name="lePktLenMin" > <widget class="QLineEdit" name="lePktLenMin" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" > <property name="text" >
<string>64</string> <string>64</string>
</property> </property>
@ -174,6 +177,9 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
<item row="1" column="2" > <item row="1" column="2" >
<widget class="QLineEdit" name="lePktLenMax" > <widget class="QLineEdit" name="lePktLenMax" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" > <property name="text" >
<string>64</string> <string>64</string>
</property> </property>
@ -373,6 +379,9 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
<item> <item>
<widget class="QRadioButton" name="rbL3Ipv4" > <widget class="QRadioButton" name="rbL3Ipv4" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" > <property name="text" >
<string>IPv4</string> <string>IPv4</string>
</property> </property>
@ -383,18 +392,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
<item> <item>
<widget class="QRadioButton" name="rbL3Arp" > <widget class="QRadioButton" name="rbL3Arp" >
<property name="text" >
<string>ARP</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rbL3Other" >
<property name="enabled" > <property name="enabled" >
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="text" > <property name="text" >
<string>Other</string> <string>ARP</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -420,7 +422,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
<item row="0" column="1" > <item row="0" column="1" >
<widget class="QRadioButton" name="rbL4Icmp" > <widget class="QRadioButton" name="rbL4Icmp" >
<property name="enabled" > <property name="enabled" >
<bool>true</bool> <bool>false</bool>
</property> </property>
<property name="text" > <property name="text" >
<string>ICMP</string> <string>ICMP</string>
@ -430,7 +432,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
<item row="0" column="2" > <item row="0" column="2" >
<widget class="QRadioButton" name="rbL4Igmp" > <widget class="QRadioButton" name="rbL4Igmp" >
<property name="enabled" > <property name="enabled" >
<bool>true</bool> <bool>false</bool>
</property> </property>
<property name="text" > <property name="text" >
<string>IGMP</string> <string>IGMP</string>
@ -440,7 +442,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
<item row="1" column="0" > <item row="1" column="0" >
<widget class="QRadioButton" name="rbL4Tcp" > <widget class="QRadioButton" name="rbL4Tcp" >
<property name="enabled" > <property name="enabled" >
<bool>true</bool> <bool>false</bool>
</property> </property>
<property name="text" > <property name="text" >
<string>TCP</string> <string>TCP</string>
@ -449,21 +451,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
<item row="1" column="1" > <item row="1" column="1" >
<widget class="QRadioButton" name="rbL4Udp" > <widget class="QRadioButton" name="rbL4Udp" >
<property name="enabled" >
<bool>true</bool>
</property>
<property name="text" >
<string>UDP</string>
</property>
</widget>
</item>
<item row="1" column="2" >
<widget class="QRadioButton" name="rbL4Other" >
<property name="enabled" > <property name="enabled" >
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="text" > <property name="text" >
<string>Other</string> <string>UDP</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -483,6 +475,19 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="1" column="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab_4" > <widget class="QWidget" name="tab_4" >
@ -1054,7 +1059,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2" > <item row="0" column="3" >
<layout class="QGridLayout" > <layout class="QGridLayout" >
<item row="0" column="0" > <item row="0" column="0" >
<widget class="QLabel" name="label_25" > <widget class="QLabel" name="label_25" >
@ -1130,7 +1135,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="0" colspan="3" > <item row="1" column="0" colspan="4" >
<widget class="QGroupBox" name="groupBox_7" > <widget class="QGroupBox" name="groupBox_7" >
<property name="title" > <property name="title" >
<string/> <string/>
@ -1206,6 +1211,9 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
<item row="1" column="3" > <item row="1" column="3" >
<widget class="QLineEdit" name="leIpSrcAddrCount" > <widget class="QLineEdit" name="leIpSrcAddrCount" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" > <property name="text" >
<string/> <string/>
</property> </property>
@ -1213,6 +1221,9 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
<item row="1" column="4" > <item row="1" column="4" >
<widget class="QLineEdit" name="leIpSrcAddrMask" > <widget class="QLineEdit" name="leIpSrcAddrMask" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" > <property name="text" >
<string>255.255.255.255</string> <string>255.255.255.255</string>
</property> </property>
@ -1264,6 +1275,9 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
<item row="2" column="3" > <item row="2" column="3" >
<widget class="QLineEdit" name="leIpDstAddrCount" > <widget class="QLineEdit" name="leIpDstAddrCount" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" > <property name="text" >
<string/> <string/>
</property> </property>
@ -1271,6 +1285,9 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
<item row="2" column="4" > <item row="2" column="4" >
<widget class="QLineEdit" name="leIpDstAddrMask" > <widget class="QLineEdit" name="leIpDstAddrMask" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" > <property name="text" >
<string>255.255.255.255</string> <string>255.255.255.255</string>
</property> </property>
@ -1279,7 +1296,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="2" column="0" colspan="3" > <item row="2" column="0" colspan="4" >
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<item> <item>
<widget class="QLabel" name="label_29" > <widget class="QLabel" name="label_29" >
@ -1310,14 +1327,14 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
</item> </item>
</layout> </layout>
</item> </item>
<item row="3" column="0" colspan="3" > <item row="3" column="0" colspan="4" >
<spacer> <spacer>
<property name="orientation" > <property name="orientation" >
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeHint" > <property name="sizeHint" >
<size> <size>
<width>470</width> <width>469</width>
<height>16</height> <height>16</height>
</size> </size>
</property> </property>
@ -1355,7 +1372,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
<item> <item>
<widget class="QStackedWidget" name="swL4Proto" > <widget class="QStackedWidget" name="swL4Proto" >
<property name="currentIndex" > <property name="currentIndex" >
<number>1</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="page" > <widget class="QWidget" name="page" >
<layout class="QGridLayout" > <layout class="QGridLayout" >

View File

@ -169,9 +169,9 @@ message StreamCore {
} }
enum DataPatternMode { enum DataPatternMode {
e_dp_fixed = 0; e_dp_fixed_word = 0;
e_dp_inc = 1; e_dp_inc_byte = 1;
e_dp_dec = 2; e_dp_dec_byte = 2;
e_dp_random = 3; e_dp_random = 3;
} }
@ -195,8 +195,8 @@ message StreamCore {
// Frame Length (includes CRC) // Frame Length (includes CRC)
optional FrameLengthMode len_mode = 14 [default = e_fl_fixed]; optional FrameLengthMode len_mode = 14 [default = e_fl_fixed];
optional uint32 frame_len = 15 [default = 64]; optional uint32 frame_len = 15 [default = 64];
optional uint32 frame_len_min = 16; optional uint32 frame_len_min = 16 [default = 64];
optional uint32 frame_len_max = 17; optional uint32 frame_len_max = 17 [default = 1518];
// Currently Selected Protocols // Currently Selected Protocols
optional FrameType ft = 21 [default = e_ft_none]; optional FrameType ft = 21 [default = e_ft_none];

View File

@ -12,65 +12,105 @@
#define LOG(...) {sprintf(logStr, __VA_ARGS__); host->Log(logStr);} #define LOG(...) {sprintf(logStr, __VA_ARGS__); host->Log(logStr);}
#define MB (1024*1024) #define MB (1024*1024)
#if 0 quint32 StreamInfo::pseudoHdrCksumPartial(quint32 srcIp, quint32 dstIp,
quint16 StreamInfo::ipv4Cksum(quint16 ipHdrLen, quint16 buff[]) quint8 protocol, quint16 len)
{ {
quint16 word16; quint32 sum;
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 = srcIp >> 16;
sum = ~sum; sum += srcIp & 0xFFFF;
sum += dstIp >> 16;
return (quint16) sum; sum += dstIp & 0xFFFF;
sum += (quint16) (protocol);
sum += len;
// Above calculation done assuming 'big endian' - so convert to host order
return qFromBigEndian(sum);
} }
#endif
quint16 StreamInfo::ipv4Cksum(uchar *buf, int len) quint32 StreamInfo::ipv4CksumPartial(uchar *buf, int len)
{ {
quint32 sum = 0; /* assume 32 bit long, 16 bit short */ quint32 sum = 0;
quint16 *ip = (quint16*) buf; quint16 *ip = (quint16*) buf;
while(len > 1) if (len & 0x0001)
{
qFatal("Cannot calculate partial checksum on non multiple of 2 length");
return 0;
}
while(len)
{ {
sum += *ip; sum += *ip;
if(sum & 0x80000000) /* if high order bit set, fold */ if(sum & 0x80000000)
sum = (sum & 0xFFFF) + (sum >> 16); sum = (sum & 0xFFFF) + (sum >> 16);
ip++; ip++;
len -= 2; len -= 2;
} }
if(len) /* take care of left over byte */ return sum;
}
quint16 StreamInfo::ipv4Cksum(uchar *buf, int len, quint32 partialSum)
{
quint32 sum = partialSum;
quint16 *ip = (quint16*) buf;
while(len > 1)
{
sum += *ip;
if(sum & 0x80000000)
sum = (sum & 0xFFFF) + (sum >> 16);
ip++;
len -= 2;
}
if (len)
sum += (unsigned short) *(unsigned char *)ip; sum += (unsigned short) *(unsigned char *)ip;
while(sum>>16) while(sum>>16)
sum = (sum & 0xFFFF) + (sum >> 16); sum = (sum & 0xFFFF) + (sum >> 16);
qDebug("cksum = %x", ~sum);
return (quint16) ~sum; return (quint16) ~sum;
} }
int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n) int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
{ {
int u, pktLen, len = 0; int u, pktLen, dataLen, len = 0;
quint32 srcIp, dstIp; // need it later for TCP/UDP cksum calculation
quint32 cumCksum = 0; // cumulative cksum used to combine partial cksums
int tcpOfs, udpOfs; // needed to fill in cksum later
uchar scratch[8]; uchar scratch[8];
// TODO(HI): use FrameLengthMode - don't assume fixed // Decide a frame length based on length mode
switch(d.core().len_mode())
{
case OstProto::StreamCore::e_fl_fixed:
pktLen = d.core().frame_len();
break;
case OstProto::StreamCore::e_fl_inc:
pktLen = d.core().frame_len_min() + (n %
(d.core().frame_len_max() - d.core().frame_len_min() + 1));
break;
case OstProto::StreamCore::e_fl_dec:
pktLen = d.core().frame_len_max() - (n %
(d.core().frame_len_max() - d.core().frame_len_min() + 1));
break;
case OstProto::StreamCore::e_fl_random:
pktLen = d.core().frame_len_min() + (qrand() %
(d.core().frame_len_max() - d.core().frame_len_min() + 1));
break;
default:
qWarning("Unhandled len mode %d. Using default 64",
d.core().len_mode());
pktLen = 64;
break;
}
// pktLen is adjusted for CRC/FCS which will be added by the NIC // pktLen is adjusted for CRC/FCS which will be added by the NIC
pktLen = d.core().frame_len() - 4; pktLen -= 4;
if (bufMaxSize < pktLen)
if ((pktLen < 0) || (pktLen > bufMaxSize))
return 0; return 0;
// We always have a Mac Header! // We always have a Mac Header!
@ -226,30 +266,34 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
qToBigEndian((quint16) 0, buf+len); qToBigEndian((quint16) 0, buf+len);
len += 2; len += 2;
// TODO(HI): Use IpMode - don't assume fixed // Get Src/Dst IP for this packet using respective IpMode
switch(d.ip().src_ip_mode()) switch(d.ip().src_ip_mode())
{ {
case OstProto::Ip::e_im_fixed: case OstProto::Ip::e_im_fixed:
qToBigEndian((quint32) d.ip().src_ip(), buf+len); srcIp = (quint32) d.ip().src_ip();
qToBigEndian(srcIp, buf+len);
break; break;
case OstProto::Ip::e_im_inc_host: case OstProto::Ip::e_im_inc_host:
u = n % d.ip().src_ip_count(); u = n % d.ip().src_ip_count();
subnet = d.ip().src_ip() & d.ip().src_ip_mask(); subnet = d.ip().src_ip() & d.ip().src_ip_mask();
host = (((d.ip().src_ip() & ~d.ip().src_ip_mask()) + u) & host = (((d.ip().src_ip() & ~d.ip().src_ip_mask()) + u) &
~d.ip().src_ip_mask()); ~d.ip().src_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len); srcIp = (quint32) (subnet | host);
qToBigEndian(srcIp, buf+len);
break; break;
case OstProto::Ip::e_im_dec_host: case OstProto::Ip::e_im_dec_host:
u = n % d.ip().src_ip_count(); u = n % d.ip().src_ip_count();
subnet = d.ip().src_ip() & d.ip().src_ip_mask(); subnet = d.ip().src_ip() & d.ip().src_ip_mask();
host = (((d.ip().src_ip() & ~d.ip().src_ip_mask()) - u) & host = (((d.ip().src_ip() & ~d.ip().src_ip_mask()) - u) &
~d.ip().src_ip_mask()); ~d.ip().src_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len); srcIp = (quint32) (subnet | host);
qToBigEndian(srcIp, buf+len);
break; break;
case OstProto::Ip::e_im_random_host: case OstProto::Ip::e_im_random_host:
subnet = d.ip().src_ip() & d.ip().src_ip_mask(); subnet = d.ip().src_ip() & d.ip().src_ip_mask();
host = (qrand() & ~d.ip().src_ip_mask()); host = (qrand() & ~d.ip().src_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len); srcIp = (quint32) (subnet | host);
qToBigEndian(srcIp, buf+len);
break; break;
default: default:
qWarning("Unhandled src_ip_mode = %d", d.ip().src_ip_mode()); qWarning("Unhandled src_ip_mode = %d", d.ip().src_ip_mode());
@ -259,26 +303,30 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
switch(d.ip().dst_ip_mode()) switch(d.ip().dst_ip_mode())
{ {
case OstProto::Ip::e_im_fixed: case OstProto::Ip::e_im_fixed:
qToBigEndian((quint32) d.ip().dst_ip(), buf+len); dstIp = (quint32) d.ip().dst_ip();
qToBigEndian(dstIp, buf+len);
break; break;
case OstProto::Ip::e_im_inc_host: case OstProto::Ip::e_im_inc_host:
u = n % d.ip().dst_ip_count(); u = n % d.ip().dst_ip_count();
subnet = d.ip().dst_ip() & d.ip().dst_ip_mask(); subnet = d.ip().dst_ip() & d.ip().dst_ip_mask();
host = (((d.ip().dst_ip() & ~d.ip().dst_ip_mask()) + u) & host = (((d.ip().dst_ip() & ~d.ip().dst_ip_mask()) + u) &
~d.ip().dst_ip_mask()); ~d.ip().dst_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len); dstIp = (quint32) (subnet | host);
qToBigEndian(dstIp, buf+len);
break; break;
case OstProto::Ip::e_im_dec_host: case OstProto::Ip::e_im_dec_host:
u = n % d.ip().dst_ip_count(); u = n % d.ip().dst_ip_count();
subnet = d.ip().dst_ip() & d.ip().dst_ip_mask(); subnet = d.ip().dst_ip() & d.ip().dst_ip_mask();
host = (((d.ip().dst_ip() & ~d.ip().dst_ip_mask()) - u) & host = (((d.ip().dst_ip() & ~d.ip().dst_ip_mask()) - u) &
~d.ip().dst_ip_mask()); ~d.ip().dst_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len); dstIp = (quint32) (subnet | host);
qToBigEndian(dstIp, buf+len);
break; break;
case OstProto::Ip::e_im_random_host: case OstProto::Ip::e_im_random_host:
subnet = d.ip().dst_ip() & d.ip().dst_ip_mask(); subnet = d.ip().dst_ip() & d.ip().dst_ip_mask();
host = (qrand() & ~d.ip().dst_ip_mask()); host = (qrand() & ~d.ip().dst_ip_mask());
qToBigEndian((quint32) (subnet | host), buf+len); dstIp = (quint32) (subnet | host);
qToBigEndian(dstIp, buf+len);
break; break;
default: default:
qWarning("Unhandled dst_ip_mode = %d", d.ip().dst_ip_mode()); qWarning("Unhandled dst_ip_mode = %d", d.ip().dst_ip_mode());
@ -291,6 +339,7 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
else else
*((quint16*)(buf + ipOfs + 10)) = ipv4Cksum(buf + ipOfs, len-ipOfs); *((quint16*)(buf + ipOfs + 10)) = ipv4Cksum(buf + ipOfs, len-ipOfs);
break; break;
} }
case OstProto::StreamCore::e_l3_arp: case OstProto::StreamCore::e_l3_arp:
// TODO(LOW) // TODO(LOW)
@ -305,6 +354,10 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
break; break;
case OstProto::StreamCore::e_l4_tcp: case OstProto::StreamCore::e_l4_tcp:
{ {
tcpOfs = len;
cumCksum = pseudoHdrCksumPartial(srcIp, dstIp, 6, pktLen - len);
qToBigEndian((quint16) d.tcp().src_port(), buf+len); qToBigEndian((quint16) d.tcp().src_port(), buf+len);
len += 2; len += 2;
qToBigEndian((quint16) d.tcp().dst_port(), buf+len); qToBigEndian((quint16) d.tcp().dst_port(), buf+len);
@ -318,26 +371,30 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
if (d.tcp().is_override_hdrlen()) if (d.tcp().is_override_hdrlen())
buf[len+0] = (quint8) d.tcp().hdrlen_rsvd(); buf[len+0] = (quint8) d.tcp().hdrlen_rsvd();
else else
buf[len+0] = (quint8) 0x50; // FIXME(LOW) buf[len+0] = (quint8) 0x50; // FIXME(LOW): Hardcoding
buf[len+1] = (quint8) d.tcp().flags(); buf[len+1] = (quint8) d.tcp().flags();
len += 2; len += 2;
qToBigEndian((quint16) d.tcp().window(), buf+len); qToBigEndian((quint16) d.tcp().window(), buf+len);
len +=2; len +=2;
if (d.tcp().is_override_cksum()) // Fill in cksum as 0 for cksum calculation, actual cksum filled later
qToBigEndian((quint16) d.tcp().cksum(), buf+len); qToBigEndian((quint16) 0, buf+len);
else
qToBigEndian((quint16) 0, buf+len); // FIXME(HI)
len +=2; len +=2;
qToBigEndian((quint16) d.tcp().urg_ptr(), buf+len); qToBigEndian((quint16) d.tcp().urg_ptr(), buf+len);
len +=2; len +=2;
// Accumulate cumulative cksum
cumCksum += ipv4CksumPartial(buf + tcpOfs, len - tcpOfs);
break; break;
} }
case OstProto::StreamCore::e_l4_udp: case OstProto::StreamCore::e_l4_udp:
{ {
int udpLen = pktLen - len; udpOfs = len;
cumCksum = pseudoHdrCksumPartial(srcIp, dstIp, 17, pktLen - len);
qToBigEndian((quint16) d.udp().src_port(), buf+len); qToBigEndian((quint16) d.udp().src_port(), buf+len);
len += 2; len += 2;
@ -347,14 +404,16 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
if (d.udp().is_override_totlen()) if (d.udp().is_override_totlen())
qToBigEndian((quint16) d.udp().totlen(), buf+len); qToBigEndian((quint16) d.udp().totlen(), buf+len);
else else
qToBigEndian((quint16) udpLen, buf+len); qToBigEndian((quint16) (pktLen - udpOfs), buf+len);
len +=2; len +=2;
if (d.udp().is_override_cksum()) // Fill in cksum as 0 for cksum calculation, actual cksum filled later
qToBigEndian((quint16) d.udp().cksum(), buf+len); qToBigEndian((quint16) 0, buf+len);
else
qToBigEndian((quint16) 0, buf+len); // FIXME(HI)
len +=2; len +=2;
// Accumulate cumulative cksum
cumCksum += ipv4CksumPartial(buf + udpOfs, len - udpOfs);
break; break;
} }
case OstProto::StreamCore::e_l4_icmp: case OstProto::StreamCore::e_l4_icmp:
@ -368,15 +427,51 @@ int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n)
} }
// Fill-in the data pattern // Fill-in the data pattern
dataLen = pktLen - len;
switch(d.core().pattern_mode())
{ {
int dataLen; case OstProto::StreamCore::e_dp_fixed_word:
for (int i = 0; i < (dataLen/4)+1; i++)
qToBigEndian((quint32) d.core().pattern(), buf+len+(i*4));
break;
case OstProto::StreamCore::e_dp_inc_byte:
for (int i = 0; i < dataLen; i++)
buf[len + i] = i % (0xFF + 1);
break;
case OstProto::StreamCore::e_dp_dec_byte:
for (int i = 0; i < dataLen; i++)
buf[len + i] = 0xFF - (i % (0xFF + 1));
break;
case OstProto::StreamCore::e_dp_random:
for (int i = 0; i < dataLen; i++)
buf[len + i] = qrand() % (0xFF + 1);
break;
default:
qWarning("Unhandled data pattern %d", d.core().pattern_mode());
}
dataLen = pktLen - len; // Calculate TCP/UDP checksum over the data pattern/payload and fill in
for (int i = 0; i < (dataLen/4)+1; i++) switch (d.core().l4_proto())
{ {
// TODO(HI): Use patternMode case OstProto::StreamCore::e_l4_tcp:
qToBigEndian((quint32) d.core().pattern(), buf+len+(i*4)); if (d.tcp().is_override_cksum())
} qToBigEndian((quint16) d.tcp().cksum(), buf + tcpOfs + 16);
else
*((quint16*)(buf + tcpOfs + 16)) =
ipv4Cksum(buf + len, dataLen, cumCksum);
break;
case OstProto::StreamCore::e_l4_udp:
if (d.udp().is_override_cksum())
qToBigEndian((quint16) d.udp().cksum(), buf + udpOfs + 6);
else
*((quint16*)(buf + udpOfs + 6)) =
ipv4Cksum(buf + len, dataLen, cumCksum);
break;
case OstProto::StreamCore::e_l4_none:
case OstProto::StreamCore::e_l4_icmp:
case OstProto::StreamCore::e_l4_igmp:
// No cksum processing required
break;
} }
return pktLen; return pktLen;
@ -414,7 +509,7 @@ PortInfo::PortInfo(uint id, pcap_if_t *dev)
} }
d.mutable_port_id()->set_id(id); d.mutable_port_id()->set_id(id);
d.set_name("eth"); // FIXME(MED): suffix portid d.set_name(QString("eth%1").arg(id).toAscii().constData());
d.set_description(dev->description); d.set_description(dev->description);
d.set_is_enabled(true); // FIXME(MED):check d.set_is_enabled(true); // FIXME(MED):check
d.set_is_oper_up(true); // FIXME(MED):check d.set_is_oper_up(true); // FIXME(MED):check
@ -425,7 +520,7 @@ PortInfo::PortInfo(uint id, pcap_if_t *dev)
// We'll create sendqueue later when required // We'll create sendqueue later when required
sendQueue = NULL; sendQueue = NULL;
pcapExtra.sendQueueNumPkts = 0; pcapExtra.sendQueueCumLen.clear();
pcapExtra.txPkts = 0; pcapExtra.txPkts = 0;
pcapExtra.txBytes = 0; pcapExtra.txBytes = 0;
isSendQueueDirty=true; isSendQueueDirty=true;
@ -446,7 +541,7 @@ void PortInfo::update()
// TODO(LOW): calculate sendqueue size // TODO(LOW): calculate sendqueue size
sendQueue = pcap_sendqueue_alloc(1*MB); sendQueue = pcap_sendqueue_alloc(1*MB);
pcapExtra.sendQueueNumPkts = 0; pcapExtra.sendQueueCumLen.clear();
// First sort the streams by ordinalValue // First sort the streams by ordinalValue
qSort(streamList); qSort(streamList);
@ -457,35 +552,45 @@ void PortInfo::update()
{ {
int numPackets, numBursts; int numPackets, numBursts;
if (streamList[i].d.control().unit() == switch (streamList[i].d.control().unit())
OstProto::StreamControl::e_su_bursts)
{ {
case OstProto::StreamControl::e_su_bursts:
numBursts = streamList[i].d.control().num_bursts(); numBursts = streamList[i].d.control().num_bursts();
numPackets = streamList[i].d.control().packets_per_burst(); numPackets = streamList[i].d.control().packets_per_burst();
} break;
else case OstProto::StreamControl::e_su_packets:
{
numBursts = 1; numBursts = 1;
numPackets = streamList[i].d.control().num_packets(); numPackets = streamList[i].d.control().num_packets();
break;
default:
qWarning("Unhandled stream control unit %d",
streamList[i].d.control().unit());
continue;
} }
for (int j = 0; j < numBursts; j++) for (int j = 0; j < numBursts; j++)
{ {
for (int k = 0; k < numPackets; k++) for (int k = 0; k < numPackets; k++)
{ {
pktHdr.len = streamList[i].makePacket( int len;
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, len = streamList[i].makePacket(pktBuf, sizeof(pktBuf),
(u_char*) pktBuf)) j * numPackets + k);
if (len > 0)
{ {
qDebug("[port %d] sendqueue_queue() failed for " pktHdr.caplen = pktHdr.len = len;
"streamidx %d\n", id(), i); 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.sendQueueCumLen.append(sendQueue->len);
} }
else
pcapExtra.sendQueueNumPkts++;
} }
} }
} }
@ -496,7 +601,7 @@ void PortInfo::update()
void PortInfo::startTransmit() void PortInfo::startTransmit()
{ {
uint bytes; uint bytes, pkts;
// TODO(HI): Stream Mode - one pass/continuous // TODO(HI): Stream Mode - one pass/continuous
bytes = pcap_sendqueue_transmit(devHandle, sendQueue, false); bytes = pcap_sendqueue_transmit(devHandle, sendQueue, false);
@ -504,21 +609,35 @@ void PortInfo::startTransmit()
{ {
qDebug("port %d: sent (%d/%d) error %s. TxStats may be inconsistent", qDebug("port %d: sent (%d/%d) error %s. TxStats may be inconsistent",
id(), bytes, sendQueue->len, pcap_geterr(devHandle)); id(), bytes, sendQueue->len, pcap_geterr(devHandle));
//! \TODO parse sendqueue using 'bytes' to get actual pkts sent
pcapExtra.txPkts += pcapExtra.sendQueueNumPkts; // parse sendqueue using 'bytes' to get actual pkts sent
pcapExtra.txBytes += bytes; #if 0
// FIXME(LOW): Get this working
pkts = qUpperBound(pcapExtra.sendQueueCumLen, bytes);
#else
for (int i = 0; i < pcapExtra.sendQueueCumLen.size(); i++)
{
if (pcapExtra.sendQueueCumLen.at(i) > bytes)
{
pkts = i;
break;
}
}
#endif
} }
else else
{ {
qDebug("port %d: sent (%d/%d) bytes\n", id(), bytes, sendQueue->len); qDebug("port %d: sent (%d/%d) bytes\n", id(), bytes, sendQueue->len);
pcapExtra.txPkts += pcapExtra.sendQueueNumPkts; pkts = pcapExtra.sendQueueCumLen.size();
pcapExtra.txBytes += bytes;
} }
// pcap_sendqueue_transmit() returned 'bytes' includes size of pcap_pkthdr // pcap_sendqueue_transmit() returned 'bytes' includes size of pcap_pkthdr
// - adjust for it // - adjust for it
pcapExtra.txBytes -= pcapExtra.sendQueueNumPkts * sizeof(pcap_pkthdr); if (bytes)
bytes -= pkts * sizeof(pcap_pkthdr);
pcapExtra.txPkts += pkts;
pcapExtra.txBytes += bytes;
} }
void PortInfo::stopTransmit() void PortInfo::stopTransmit()
@ -951,7 +1070,7 @@ const ::OstProto::PortIdList* request,
portIdx = request->port_id(i).id(); portIdx = request->port_id(i).id();
if (portIdx >= numPorts) if (portIdx >= numPorts)
continue; // FIXME(MED): partial RPC? continue; // TODO(LOW): partial RPC?
if (portInfo[portIdx]->isDirty()) if (portInfo[portIdx]->isDirty())
portInfo[portIdx]->update(); portInfo[portIdx]->update();
@ -963,7 +1082,7 @@ const ::OstProto::PortIdList* request,
portIdx = request->port_id(i).id(); portIdx = request->port_id(i).id();
if (portIdx >= numPorts) if (portIdx >= numPorts)
continue; // FIXME(MED): partial RPC? continue; // TODO(LOW): partial RPC?
portInfo[portIdx]->startTransmit(); portInfo[portIdx]->startTransmit();
} }
@ -986,7 +1105,7 @@ const ::OstProto::PortIdList* request,
portIdx = request->port_id(i).id(); portIdx = request->port_id(i).id();
if (portIdx >= numPorts) if (portIdx >= numPorts)
continue; // FIXME(MED): partial RPC? continue; // TODO(LOW): partial RPC?
portInfo[portIdx]->stopTransmit(); portInfo[portIdx]->stopTransmit();
} }
@ -1038,7 +1157,7 @@ const ::OstProto::PortIdList* request,
portidx = request->port_id(i).id(); portidx = request->port_id(i).id();
if (portidx >= numPorts) if (portidx >= numPorts)
continue; // FIXME(med): partial rpc? continue; // TODO(LOW): partial rpc?
s = response->add_port_stats(); s = response->add_port_stats();
s->mutable_port_id()->set_id(request->port_id(i).id()); s->mutable_port_id()->set_id(request->port_id(i).id());
@ -1082,7 +1201,7 @@ const ::OstProto::PortIdList* request,
portIdx = request->port_id(i).id(); portIdx = request->port_id(i).id();
if (portIdx >= numPorts) if (portIdx >= numPorts)
continue; // FIXME(MED): partial RPC? continue; // TODO(LOW): partial RPC?
portInfo[portIdx]->resetStats(); portInfo[portIdx]->resetStats();
} }

View File

@ -37,8 +37,10 @@ class StreamInfo
StreamInfo() { PbHelper pbh; pbh.ForceSetSingularDefault(&d); } StreamInfo() { PbHelper pbh; pbh.ForceSetSingularDefault(&d); }
//quint16 ipv4Cksum(quint16 ipHdrLen, quint16 buff[]); quint32 pseudoHdrCksumPartial(quint32 srcIp, quint32 dstIp,
quint16 ipv4Cksum(uchar *buf, int len); quint8 protocol, quint16 len);
quint32 ipv4CksumPartial(uchar *buf, int len);
quint16 ipv4Cksum(uchar *buf, int len, quint32 partialSum = 0);
int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n); int StreamInfo::makePacket(uchar *buf, int bufMaxSize, int n);
public: public:
bool operator < (const StreamInfo &s) const bool operator < (const StreamInfo &s) const
@ -90,8 +92,10 @@ class PortInfo
// PCAP supports it, we'll remove from here // PCAP supports it, we'll remove from here
struct PcapExtra struct PcapExtra
{ {
//! pcap_sendqueue_transmit() only returns 'bytes' sent //! Used to track num of packets (and their sizes) in the
uint sendQueueNumPkts; // send queue. Also used to find out actual num of pkts sent
// in case of partial send in pcap_sendqueue_transmit()
QList<uint> sendQueueCumLen;
//! PCAP doesn't do any tx stats //! PCAP doesn't do any tx stats
quint64 txPkts; quint64 txPkts;