Implemented "exclusive control" for a port using bindconfig (Win32 only). Following changes done for the same -

- OstProto service has a new method "modifyPort()"
- At port init port.isExclusive is now set using a bindconfig query (Win32 only)
- AbstractPort interface has 2 new pure virtual methods - hasExclusiveControl() and setExclusiveControl()
- PcapPort does not support this functionality (yet) so these methods return false
- WinPcapPort suppots this new functionality using bindconfig
- Port's notes (specifying Rx/Tx limitations) are now set and updated based on hasExclusiveControl()
- Presence of 'notes' on a port is indicated using a '*' after the port name in the port stats window
- The tabwidget has been removed from Port Window | Stream View Pane
- Ostinato Client has a new action in the port window's context menu for the same
- Port Icon in the Port Window is decorated based on exclusive control
This commit is contained in:
Srivats P. 2010-02-09 15:21:52 +00:00
parent 70ca42fbb3
commit b28bcd3055
23 changed files with 356 additions and 152 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 793 B

View File

@ -12,6 +12,7 @@
<file>icons/bullet_yellow.png</file>
<file>icons/control_play.png</file>
<file>icons/control_stop.png</file>
<file>icons/deco_exclusive.png</file>
<file>icons/delete.png</file>
<file>icons/magnifier.png</file>
<file>icons/portgroup_add.png</file>

View File

@ -22,6 +22,7 @@ Port::Port(quint32 id, quint32 portGroupId)
Port::~Port()
{
qDebug("%s", __FUNCTION__);
while (!mStreams.isEmpty())
delete mStreams.takeFirst();
}

View File

@ -31,7 +31,6 @@ class Port : public QObject {
public:
enum AdminStatus { AdminDisable, AdminEnable };
enum ControlMode { ControlShared, ControlExclusive };
// FIXME(HIGH): default args is a hack for QList operations on Port
Port(quint32 id = 0xFFFFFFFF, quint32 pgId = 0xFFFFFFFF);
@ -50,8 +49,8 @@ public:
{ return QString().fromStdString(d.notes()); }
AdminStatus adminStatus()
{ return (d.is_enabled()?AdminEnable:AdminDisable); }
ControlMode controlMode()
{ return (d.is_exclusive_control()?ControlExclusive:ControlShared); }
bool hasExclusiveControl()
{ return d.is_exclusive_control(); }
//void setAdminEnable(AdminStatus status) { mAdminStatus = status; }
void setAlias(QString &alias) { mUserAlias = alias; }

View File

@ -32,7 +32,7 @@ PortGroup::PortGroup(QHostAddress ip, quint16 port)
// FIXME(LOW):Can't for my life figure out why this ain't working!
//QMetaObject::connectSlotsByName(this);
connect(rpcChannel, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this, SLOT(on_rpcChannel_stateChanged()));
this, SLOT(on_rpcChannel_stateChanged(QAbstractSocket::SocketState)));
connect(rpcChannel, SIGNAL(connected()),
this, SLOT(on_rpcChannel_connected()));
connect(rpcChannel, SIGNAL(disconnected()),
@ -56,9 +56,9 @@ PortGroup::~PortGroup()
// ------------------------------------------------
// Slots
// ------------------------------------------------
void PortGroup::on_rpcChannel_stateChanged()
void PortGroup::on_rpcChannel_stateChanged(QAbstractSocket::SocketState state)
{
qDebug("state changed");
qDebug("state changed %d", state);
emit portGroupDataChanged(mPortGroupId);
}
@ -275,6 +275,80 @@ _error_exit:
delete portConfigList;
}
void PortGroup::modifyPort(int portIndex, bool isExclusive)
{
OstProto::PortConfigList portConfigList;
OstProto::Port *port;
OstProto::Ack *ack;
qDebug("%s: portIndex = %d", __FUNCTION__, portIndex);
Q_ASSERT(portIndex < mPorts.size());
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
mainWindow->setDisabled(true);
port = portConfigList.add_port();
port->mutable_port_id()->set_id(mPorts[portIndex]->id());
port->set_is_exclusive_control(isExclusive);
ack = new OstProto::Ack;
rpcController->Reset();
serviceStub->modifyPort(rpcController, &portConfigList, ack,
NewCallback(this, &PortGroup::processModifyPortAck, portIndex, ack));
}
void PortGroup::processModifyPortAck(int portIndex, OstProto::Ack *ack)
{
OstProto::PortIdList portIdList;
OstProto::PortId *portId;
OstProto::PortConfigList *portConfigList;
qDebug("In %s", __FUNCTION__);
portId = portIdList.add_port_id();
portId->set_id(mPorts[portIndex]->id());
portConfigList = new OstProto::PortConfigList;
rpcController->Reset();
serviceStub->getPortConfig(rpcController, &portIdList, portConfigList,
NewCallback(this, &PortGroup::processUpdatedPortConfig,
portConfigList));
delete ack;
}
void PortGroup::processUpdatedPortConfig(OstProto::PortConfigList *portConfigList)
{
qDebug("In %s", __FUNCTION__);
if (rpcController->Failed())
{
qDebug("%s: rpc failed", __FUNCTION__);
goto _exit;
}
if (portConfigList->port_size() != 1)
qDebug("port size = %d (expected = 1)", portConfigList->port_size());
for(int i = 0; i < portConfigList->port_size(); i++)
{
uint id;
id = portConfigList->port(i).port_id().id();
// FIXME: don't mix port id & index into mPorts[]
mPorts[id]->updatePortConfig(portConfigList->mutable_port(i));
}
emit portGroupDataChanged(mPortGroupId);
_exit:
mainWindow->setEnabled(true);
QApplication::restoreOverrideCursor();
delete portConfigList;
}
void PortGroup::getStreamIdList(int portIndex,
OstProto::StreamIdList *streamIdList)
{

View File

@ -23,21 +23,19 @@ class PortGroup : public QObject {
Q_OBJECT
private:
quint32 mPortGroupId;
static quint32 mPortGroupAllocId;
QString mUserAlias; // user defined
#if 0 // PB
QTcpSocket *mpSocket;
QHostAddress mServerAddress;
quint16 mServerPort;
#endif
PbRpcChannel *rpcChannel;
PbRpcController *rpcController;
PbRpcController *rpcControllerStats;
bool isGetStatsPending_;
::OstProto::OstService::Stub *serviceStub;
static quint32 mPortGroupAllocId;
quint32 mPortGroupId;
QString mUserAlias; // user defined
PbRpcChannel *rpcChannel;
PbRpcController *rpcController;
PbRpcController *rpcControllerStats;
bool isGetStatsPending_;
::OstProto::OstService::Stub *serviceStub;
::OstProto::PortIdList portIdList;
::OstProto::PortIdList portIdList;
public: // FIXME(HIGH): member access
QList<Port*> mPorts;
@ -67,6 +65,10 @@ public:
void processPortIdList(OstProto::PortIdList *portIdList);
void processPortConfigList(OstProto::PortConfigList *portConfigList);
void modifyPort(int portId, bool isExclusive);
void processModifyPortAck(int portIndex, OstProto::Ack *ack);
void processUpdatedPortConfig(OstProto::PortConfigList *portConfigList);
void getStreamIdList(int portIndex = 0,
OstProto::StreamIdList *streamIdList = NULL);
void getStreamConfigList(int portIndex = 0,
@ -98,7 +100,7 @@ signals:
void statsChanged(quint32 portGroupId);
private slots:
void on_rpcChannel_stateChanged();
void on_rpcChannel_stateChanged(QAbstractSocket::SocketState state);
void on_rpcChannel_connected();
void on_rpcChannel_disconnected();
void on_rpcChannel_error(QAbstractSocket::SocketError socketError);

View File

@ -1,6 +1,8 @@
#include "portmodel.h"
#include "portgrouplist.h"
#include <QIcon>
#include <QPainter>
#if 0
#define DBG0(x) qDebug(x)
@ -14,6 +16,23 @@ PortModel::PortModel(PortGroupList *p, QObject *parent)
: QAbstractItemModel(parent)
{
pgl = p;
portIconFactory[OstProto::LinkStateUnknown][false] =
QIcon(":/icons/bullet_white.png");
portIconFactory[OstProto::LinkStateDown][false] =
QIcon(":/icons/bullet_red.png");
portIconFactory[OstProto::LinkStateUp][false] =
QIcon(":/icons/bullet_green.png");
for (int linkState = 0; linkState < kLinkStatesCount; linkState++)
{
QPixmap pixmap(":/icons/deco_exclusive.png");
QPainter painter(&pixmap);
QIcon icon = portIconFactory[linkState][false];
painter.drawPixmap(0, 0, icon.pixmap(QSize(32,32)));
portIconFactory[linkState][true] = QIcon(pixmap);
}
}
int PortModel::rowCount(const QModelIndex &parent) const
@ -123,38 +142,27 @@ QVariant PortModel::data(const QModelIndex &index, int role) const
}
else
{
if (pgl->mPortGroups.at(parent.row())->numPorts() == 0)
{
DBG0("Exit PortModel data 4\n");
return QVariant();
}
Port *port = pgl->mPortGroups.at(parent.row())->mPorts[index.row()];
// Non Top Level - Port
if ((role == Qt::DisplayRole))
{
DBG0("Exit PortModel data 4\n");
if (pgl->mPortGroups.at(parent.row())->numPorts() == 0)
return QVariant();
return QString("Port %1: %2 [%3] (%4)").
arg(pgl->mPortGroups.at(
parent.row())->mPorts[index.row()]->id()).
arg(pgl->mPortGroups.at(
parent.row())->mPorts[index.row()]->name()).
arg(QHostAddress("0.0.0.0").toString()). // FIXME(LOW)
arg(pgl->mPortGroups.at(
parent.row())->mPorts[index.row()]->description());
// FIXME(LOW) - IP Address below
return QString("Port %1: %2 [%3] (%4)")
.arg(port->id())
.arg(port->name())
.arg(QHostAddress("0.0.0.0").toString())
.arg(port->description());
}
else if ((role == Qt::DecorationRole))
{
DBG0("Exit PortModel data 5\n");
if (pgl->mPortGroups.at(parent.row())->numPorts() == 0)
return QVariant();
switch(pgl->mPortGroups.at(parent.row())->mPorts[index.row()]->linkState())
{
case OstProto::LinkStateUnknown:
return QIcon(":/icons/bullet_white.png");
case OstProto::LinkStateDown:
return QIcon(":/icons/bullet_red.png");
case OstProto::LinkStateUp:
return QIcon(":/icons/bullet_green.png");
default:
qFatal("unexpected/unimplemented port oper state");
}
return portIconFactory[port->linkState()][port->hasExclusiveControl()];
}
else
{
@ -235,7 +243,7 @@ QModelIndex PortModel::parent(const QModelIndex &index) const
bool PortModel::isPortGroup(const QModelIndex& index)
{
if ((index.internalId() & 0xFFFF) == 0xFFFF)
if (index.isValid() && ((index.internalId() & 0xFFFF) == 0xFFFF))
return true;
else
return false;
@ -243,7 +251,7 @@ bool PortModel::isPortGroup(const QModelIndex& index)
bool PortModel::isPort(const QModelIndex& index)
{
if ((index.internalId() & 0xFFFF) != 0xFFFF)
if (index.isValid() && ((index.internalId() & 0xFFFF) != 0xFFFF))
return true;
else
return false;

View File

@ -2,6 +2,7 @@
#define _PORT_MODEL_H
#include <QAbstractItemModel>
#include <QIcon>
class PortGroupList;
class PortGroup;
@ -12,24 +13,29 @@ class PortModel : public QAbstractItemModel
friend class PortGroupList;
public:
PortModel(PortGroupList *p, QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
QModelIndex index (int row, int col,
const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
bool isPortGroup(const QModelIndex& index);
bool isPort(const QModelIndex& index);
quint32 portGroupId(const QModelIndex& index);
quint32 portId(const QModelIndex& index);
private:
PortGroupList *pgl;
public:
PortModel(PortGroupList *p, QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index (int row, int col, const QModelIndex & parent = QModelIndex() ) const;
QModelIndex parent(const QModelIndex &index) const;
bool isPortGroup(const QModelIndex& index);
bool isPort(const QModelIndex& index);
quint32 portGroupId(const QModelIndex& index);
quint32 portId(const QModelIndex& index);
static const int kLinkStatesCount = 3;
static const int kExclusiveStatesCount = 2;
QIcon portIconFactory[kLinkStatesCount][kExclusiveStatesCount];
private slots:
void when_portGroupDataChanged(int portGroupId, int portId);
@ -45,7 +51,6 @@ private slots:
void triggerLayoutAboutToBeChanged();
void triggerLayoutChanged();
#endif
};
#endif

View File

@ -193,9 +193,18 @@ QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, in
if (orientation == Qt::Horizontal)
{
uint portGroupIdx, portIdx;
QString portName;
getDomainIndexes(index(0, section), portGroupIdx, portIdx);
return QString("Port %1-%2").arg(portGroupIdx).arg(portIdx);
portName = QString("Port %1-%2").arg(portGroupIdx).arg(portIdx);
if (portGroupIdx < (uint) pgl->mPortGroups.size()
&& portIdx < (uint) pgl->mPortGroups.at(portGroupIdx)->mPorts.size())
{
if (!pgl->mPortGroups.at(portGroupIdx)->mPorts[portIdx]->notes()
.isEmpty())
portName += " *";
}
return portName;
}
else
return PortStatName.at(section);

View File

@ -16,6 +16,8 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
setupUi(this);
tvPortList->header()->hide();
tvStreamList->setItemDelegate(delegate);
tvStreamList->verticalHeader()->setDefaultSectionSize(
@ -27,6 +29,8 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
tvPortList->addAction(actionConnect_Port_Group);
tvPortList->addAction(actionDisconnect_Port_Group);
tvPortList->addAction(actionExclusive_Control);
tvStreamList->addAction(actionNew_Stream);
tvStreamList->addAction(actionEdit_Stream);
tvStreamList->addAction(actionDelete_Stream);
@ -210,6 +214,8 @@ void PortsWindow::updatePortViewActions(const QModelIndex& current)
actionDelete_Port_Group->setDisabled(true);
actionConnect_Port_Group->setDisabled(true);
actionDisconnect_Port_Group->setDisabled(true);
actionExclusive_Control->setDisabled(true);
goto _EXIT;
}
@ -219,6 +225,9 @@ void PortsWindow::updatePortViewActions(const QModelIndex& current)
if (plm->isPortGroup(current))
{
actionDelete_Port_Group->setEnabled(true);
actionExclusive_Control->setDisabled(true);
switch(plm->portGroup(current).state())
{
case QAbstractSocket::UnconnectedState:
@ -247,9 +256,15 @@ void PortsWindow::updatePortViewActions(const QModelIndex& current)
}
else if (plm->isPort(current))
{
actionDelete_Port_Group->setEnabled(false);
actionConnect_Port_Group->setEnabled(false);
actionDisconnect_Port_Group->setEnabled(false);
actionDelete_Port_Group->setDisabled(true);
actionConnect_Port_Group->setDisabled(true);
actionDisconnect_Port_Group->setDisabled(true);
actionExclusive_Control->setEnabled(true);
if (plm->port(current).hasExclusiveControl())
actionExclusive_Control->setChecked(true);
else
actionExclusive_Control->setChecked(false);
}
_EXIT:
@ -346,6 +361,15 @@ void PortsWindow::on_actionDisconnect_Port_Group_triggered()
if (current.isValid())
plm->portGroup(current).disconnectFromHost();
}
void PortsWindow::on_actionExclusive_Control_triggered(bool checked)
{
QModelIndex current = tvPortList->selectionModel()->currentIndex();
if (plm->isPort(current))
plm->portGroup(current.parent()).modifyPort(current.row(), checked);
}
#if 0
void PortsWindow::on_actionNew_Stream_triggered()
{

View File

@ -51,6 +51,8 @@ private slots:
void on_actionConnect_Port_Group_triggered();
void on_actionDisconnect_Port_Group_triggered();
void on_actionExclusive_Control_triggered(bool checked);
void on_actionNew_Stream_triggered();
void on_actionEdit_Stream_triggered();
void on_actionDelete_Stream_triggered();

View File

@ -6,7 +6,7 @@
<x>0</x>
<y>0</y>
<width>689</width>
<height>254</height>
<height>352</height>
</rect>
</property>
<property name="windowTitle" >
@ -34,7 +34,10 @@
<number>0</number>
</property>
<widget class="QWidget" name="portDetail" >
<layout class="QGridLayout" >
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
@ -47,13 +50,7 @@
<property name="bottomMargin" >
<number>0</number>
</property>
<property name="horizontalSpacing" >
<number>6</number>
</property>
<property name="verticalSpacing" >
<number>6</number>
</property>
<item row="0" column="0" >
<item>
<layout class="QHBoxLayout" >
<item>
<spacer>
@ -77,7 +74,7 @@
</item>
</layout>
</item>
<item row="1" column="0" >
<item>
<widget class="QFrame" name="frAggregate" >
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
@ -129,52 +126,23 @@
</layout>
</widget>
</item>
<item row="2" column="0" >
<widget class="QTabWidget" name="tabWidget" >
<property name="currentIndex" >
<number>0</number>
<item>
<widget class="QTableView" name="tvStreamList" >
<property name="contextMenuPolicy" >
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="lineWidth" >
<number>1</number>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior" >
<enum>QAbstractItemView::SelectRows</enum>
</property>
<widget class="QWidget" name="tab_3" >
<attribute name="title" >
<string>Control</string>
</attribute>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>0</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QTableView" name="tvStreamList" >
<property name="contextMenuPolicy" >
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="frameShape" >
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth" >
<number>0</number>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior" >
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
@ -254,6 +222,14 @@
<string>Edit Stream</string>
</property>
</action>
<action name="actionExclusive_Control" >
<property name="checkable" >
<bool>true</bool>
</property>
<property name="text" >
<string>Exclusive Control (EXPERIMENTAL)</string>
</property>
</action>
</widget>
<resources>
<include location="ostinato.qrc" />

View File

@ -1,9 +1,7 @@
// stream.proto
package OstProto;
message StreamId {
required uint32 id = 1;
required uint32 id = 1;
}
message StreamCore {
@ -136,7 +134,7 @@ message PortConfigList {
}
message StreamConfigList {
required PortId port_id = 1;
required PortId port_id = 1;
repeated Stream stream = 2;
}
@ -188,6 +186,7 @@ message PortStatsList {
service OstService {
rpc getPortIdList(Void) returns (PortIdList);
rpc getPortConfig(PortIdList) returns (PortConfigList);
rpc modifyPort(PortConfigList) returns (Ack);
rpc getStreamIdList(PortId) returns (StreamIdList);
rpc getStreamConfig(StreamIdList) returns (StreamConfigList);

View File

@ -64,7 +64,7 @@ void PbRpcChannel::CallMethod(
::google::protobuf::Closure* done)
{
char msg[MSGBUF_SIZE];
int len;
int len;
bool ret;
if (isPending)
@ -80,6 +80,7 @@ void PbRpcChannel::CallMethod(
call.done = done;
pendingCallList.append(call);
qDebug("pendingCallList size = %d", pendingCallList.size());
Q_ASSERT(pendingCallList.size() < 100);
@ -113,7 +114,7 @@ void PbRpcChannel::CallMethod(
*((quint32*)(&msg[4])) = HTONL(len); // len
// Avoid printing stats since it happens every couple of seconds
if (pendingMethodId != 12)
if (pendingMethodId != 13)
{
qDebug("client(%s) sending %d bytes encoding <%s>", __FUNCTION__,
PB_HDR_SIZE + len, req->DebugString().c_str());
@ -230,7 +231,7 @@ void PbRpcChannel::on_mpSocket_readyRead()
response->ParseFromArray((void*) msg, len);
// Avoid printing stats
if (method != 12)
if (method != 13)
{
qDebug("client(%s): Parsed as %s", __FUNCTION__,
response->DebugString().c_str());
@ -262,6 +263,7 @@ void PbRpcChannel::on_mpSocket_readyRead()
if (pendingCallList.size())
{
RpcCall call = pendingCallList.takeFirst();
qDebug("RpcChannel: executing queued method %d", call.method->index());
CallMethod(call.method, call.controller, call.request, call.response,
call.done);
}

View File

@ -104,7 +104,7 @@ void RpcServer::done(::google::protobuf::Message *request,
*((quint32*)(&msg[4])) = HTONL(len); // len
// Avoid printing stats since it happens once every couple of seconds
if (pendingMethodId != 12)
if (pendingMethodId != 13)
{
qDebug("Server(%s): sending %d bytes to client encoding <%s>",
__FUNCTION__, len + PB_HDR_SIZE, response->DebugString().c_str());

View File

@ -13,7 +13,6 @@ AbstractPort::AbstractPort(int id, const char *device)
//! \todo (LOW) admin enable/disable of port
data_.set_is_enabled(true);
//! \todo (HIGH) port exclusive control
data_.set_is_exclusive_control(false);
isSendQueueDirty_ = true;
@ -23,12 +22,29 @@ AbstractPort::AbstractPort(int id, const char *device)
resetStats();
}
AbstractPort::~AbstractPort()
{
}
void AbstractPort::init()
{
}
AbstractPort::~AbstractPort()
bool AbstractPort::modify(const OstProto::Port &port)
{
bool ret = false;
//! \todo Use reflection to find out which fields are set
if (port.has_is_exclusive_control())
{
bool val = port.is_exclusive_control();
ret = setExclusiveControl(val);
if (ret)
data_.set_is_exclusive_control(val);
}
return ret;
}
StreamBase* AbstractPort::streamAtIndex(int index)

View File

@ -33,6 +33,12 @@ public:
int id() { return data_.port_id().id(); }
void protoDataCopyInto(OstProto::Port *port) { port->CopyFrom(data_); }
bool modify(const OstProto::Port &port);
virtual OstProto::LinkState linkState() { return linkState_; }
virtual bool hasExclusiveControl() = 0;
virtual bool setExclusiveControl(bool exclusive) = 0;
int streamCount() { return streamList_.size(); }
StreamBase* streamAtIndex(int index);
StreamBase* stream(int streamId);
@ -42,8 +48,6 @@ public:
bool isDirty() { return isSendQueueDirty_; }
void setDirty() { isSendQueueDirty_ = true; }
virtual OstProto::LinkState linkState() { return linkState_; }
virtual void clearPacketList() = 0;
virtual bool appendToPacketList(long sec, long usec, const uchar *packet,
int length) = 0;

View File

@ -69,6 +69,30 @@ void MyService::getPortConfig(::google::protobuf::RpcController* /*controller*/,
done->Run();
}
void MyService::modifyPort(::google::protobuf::RpcController* /*controller*/,
const ::OstProto::PortConfigList* request,
::OstProto::Ack* /*response*/,
::google::protobuf::Closure* done)
{
qDebug("In %s", __PRETTY_FUNCTION__);
for (int i = 0; i < request->port_size(); i++)
{
OstProto::Port port;
int id;
port = request->port(i);
id = port.port_id().id();
if (id < portInfo.size())
{
portInfo[id]->modify(port);
}
}
//! \todo (LOW): fill-in response "Ack"????
done->Run();
}
void MyService::getStreamIdList(::google::protobuf::RpcController* controller,
const ::OstProto::PortId* request,
::OstProto::StreamIdList* response,

View File

@ -25,6 +25,10 @@ public:
const ::OstProto::PortIdList* request,
::OstProto::PortConfigList* response,
::google::protobuf::Closure* done);
void MyService::modifyPort(::google::protobuf::RpcController* /*controller*/,
const ::OstProto::PortConfigList* request,
::OstProto::Ack* response,
::google::protobuf::Closure* done);
virtual void getStreamIdList(::google::protobuf::RpcController* controller,
const ::OstProto::PortId* request,
::OstProto::StreamIdList* response,

View File

@ -44,24 +44,12 @@ PcapPort::PcapPort(int id, const char *device)
void PcapPort::init()
{
QString notes;
if (!monitorRx_->isDirectional() && !data_.is_exclusive_control())
notes.append("<i>Rx Frames/Bytes</i>: Includes non Ostinato Tx pkts also (Tx by Ostinato are not included)<br>");
if (!monitorTx_->isDirectional())
{
transmitter_->useExternalStats(&stats_);
notes.append("<i>Tx Frames/Bytes</i>: Only Ostinato Tx pkts (Tx by others NOT included)<br>");
}
transmitter_->setHandle(monitorRx_->handle());
if (!notes.isEmpty())
data_.set_notes(QString("<b>Limitation(s)</b>"
"<p>%1<br>"
"Rx/Tx Rates are also subject to above limitation(s)</p>").
arg(notes).toStdString());
updateNotes();
monitorRx_->start();
monitorTx_->start();
@ -75,6 +63,25 @@ PcapPort::~PcapPort()
delete monitorRx_;
}
void PcapPort::updateNotes()
{
QString notes;
if (!monitorRx_->isDirectional() && !hasExclusiveControl())
notes.append("<i>Rx Frames/Bytes</i>: Includes non Ostinato Tx pkts also (Tx by Ostinato are not included)<br>");
if (!monitorTx_->isDirectional() && !hasExclusiveControl())
notes.append("<i>Tx Frames/Bytes</i>: Only Ostinato Tx pkts (Tx by others NOT included)<br>");
if (notes.isEmpty())
data_.set_notes("");
else
data_.set_notes(QString("<b>Limitation(s)</b>"
"<p>%1<br>"
"Rx/Tx Rates are also subject to above limitation(s)</p>").
arg(notes).toStdString());
}
PcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
AbstractPort::PortStats *stats)
{

View File

@ -16,6 +16,9 @@ public:
void init();
virtual bool hasExclusiveControl() { return false; }
virtual bool setExclusiveControl(bool exclusive) { return false; }
virtual void clearPacketList() {
transmitter_->clearPacketList();
setPacketListLoopMode(false, 0);
@ -114,11 +117,14 @@ protected:
PortMonitor *monitorRx_;
PortMonitor *monitorTx_;
void updateNotes();
private:
PortTransmitter *transmitter_;
PortCapturer *capturer_;
static pcap_if_t *deviceList_;
static pcap_if_t *deviceList_;
};
#endif

View File

@ -1,5 +1,7 @@
#include "winpcapport.h"
#include <QProcess>
#ifdef Q_OS_WIN32
const uint OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114;
@ -20,6 +22,8 @@ WinPcapPort::WinPcapPort(int id, const char *device)
sizeof(uint));
if (!linkStateOid_)
qFatal("failed to alloc oidData");
data_.set_is_exclusive_control(hasExclusiveControl());
}
WinPcapPort::~WinPcapPort()
@ -53,6 +57,41 @@ OstProto::LinkState WinPcapPort::linkState()
return linkState_;
}
bool WinPcapPort::hasExclusiveControl()
{
QString portName(adapter_->Name + strlen("\\Device\\NPF_"));
int exitCode;
qDebug("%s: %s", __FUNCTION__, portName.toAscii().constData());
exitCode = QProcess::execute("bindconfig.exe",
QStringList() << "comp" << portName);
qDebug("%s: exit code %d", __FUNCTION__, exitCode);
if (exitCode == 0)
return true;
else
return false;
}
bool WinPcapPort::setExclusiveControl(bool exclusive)
{
QString portName(adapter_->Name + strlen("\\Device\\NPF_"));
QString status;
qDebug("%s: %s", __FUNCTION__, portName.toAscii().constData());
status = exclusive ? "disable" : "enable";
QProcess::execute("bindconfig.exe",
QStringList() << "comp" << portName << status);
updateNotes();
return (exclusive == hasExclusiveControl());
}
WinPcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
AbstractPort::PortStats *stats)
: PcapPort::PortMonitor(device, direction, stats)

View File

@ -16,6 +16,8 @@ public:
~WinPcapPort();
virtual OstProto::LinkState linkState();
virtual bool hasExclusiveControl();
virtual bool setExclusiveControl(bool exclusive);
protected:
class PortMonitor: public PcapPort::PortMonitor