Feature (contd.): Device Emulation - Got rid of a bunch of FIXMEs and all trailing whitespace (in the code added for this feature)
This commit is contained in:
parent
7daf75c95a
commit
3a5396c865
@ -30,6 +30,9 @@ class StreamBase;
|
|||||||
class PacketBuffer;
|
class PacketBuffer;
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
|
|
||||||
|
// TODO: send notification back to client(s)
|
||||||
|
#define notify qWarning
|
||||||
|
|
||||||
class AbstractPort
|
class AbstractPort
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -30,9 +30,9 @@ const int kBaseHex = 16;
|
|||||||
const quint64 kBcastMac = 0xffffffffffffULL;
|
const quint64 kBcastMac = 0xffffffffffffULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE:
|
* NOTE:
|
||||||
* 1. Device Key is (VLANS + MAC) - is assumed to be unique for a device
|
* 1. Device Key is (VLANS + MAC) - is assumed to be unique for a device
|
||||||
* 2. Device clients/users (viz. DeviceManager) should take care when
|
* 2. Device clients/users (viz. DeviceManager) should take care when
|
||||||
* setting params that change the key, if the key is used elsewhere
|
* setting params that change the key, if the key is used elsewhere
|
||||||
* (e.g. in a hash)
|
* (e.g. in a hash)
|
||||||
*/
|
*/
|
||||||
@ -117,14 +117,14 @@ DeviceKey Device::key()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Device::clearKey()
|
void Device::clearKey()
|
||||||
{
|
{
|
||||||
key_.fill(0, kMaxVlan * sizeof(quint16) + sizeof(quint64));
|
key_.fill(0, kMaxVlan * sizeof(quint16) + sizeof(quint64));
|
||||||
}
|
}
|
||||||
|
|
||||||
int Device::encapSize()
|
int Device::encapSize()
|
||||||
{
|
{
|
||||||
// ethernet header + vlans
|
// ethernet header + vlans
|
||||||
int size = 14 + 4*numVlanTags_;
|
int size = 14 + 4*numVlanTags_;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ int Device::encapSize()
|
|||||||
void Device::encap(PacketBuffer *pktBuf, quint64 dstMac, quint16 type)
|
void Device::encap(PacketBuffer *pktBuf, quint64 dstMac, quint16 type)
|
||||||
{
|
{
|
||||||
int ofs;
|
int ofs;
|
||||||
quint64 srcMac = mac_;
|
quint64 srcMac = mac_;
|
||||||
uchar *p = pktBuf->push(encapSize());
|
uchar *p = pktBuf->push(encapSize());
|
||||||
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
@ -306,7 +306,7 @@ void Device::receiveArp(PacketBuffer *pktBuf)
|
|||||||
// Extract tgtIp first to check quickly if this packet is for us or not
|
// Extract tgtIp first to check quickly if this packet is for us or not
|
||||||
tgtIp = qFromBigEndian<quint32>(pktData + 24);
|
tgtIp = qFromBigEndian<quint32>(pktData + 24);
|
||||||
if (tgtIp != ip4_) {
|
if (tgtIp != ip4_) {
|
||||||
qDebug("tgtIp %s is not me %s",
|
qDebug("tgtIp %s is not me %s",
|
||||||
qPrintable(QHostAddress(tgtIp).toString()),
|
qPrintable(QHostAddress(tgtIp).toString()),
|
||||||
qPrintable(QHostAddress(ip4_).toString()));
|
qPrintable(QHostAddress(ip4_).toString()));
|
||||||
return;
|
return;
|
||||||
@ -355,7 +355,7 @@ void Device::receiveArp(PacketBuffer *pktBuf)
|
|||||||
arpTable.insert(srcIp, srcMac);
|
arpTable.insert(srcIp, srcMac);
|
||||||
|
|
||||||
rspPkt = new PacketBuffer;
|
rspPkt = new PacketBuffer;
|
||||||
rspPkt->reserve(encapSize());
|
rspPkt->reserve(encapSize());
|
||||||
pktData = rspPkt->put(28);
|
pktData = rspPkt->put(28);
|
||||||
if (pktData) {
|
if (pktData) {
|
||||||
// HTYP, PTYP
|
// HTYP, PTYP
|
||||||
@ -376,7 +376,7 @@ void Device::receiveArp(PacketBuffer *pktBuf)
|
|||||||
transmitPacket(rspPkt);
|
transmitPacket(rspPkt);
|
||||||
|
|
||||||
qDebug("Sent ARP Reply for srcIp/tgtIp=%s/%s",
|
qDebug("Sent ARP Reply for srcIp/tgtIp=%s/%s",
|
||||||
qPrintable(QHostAddress(srcIp).toString()),
|
qPrintable(QHostAddress(srcIp).toString()),
|
||||||
qPrintable(QHostAddress(tgtIp).toString()));
|
qPrintable(QHostAddress(tgtIp).toString()));
|
||||||
break;
|
break;
|
||||||
case 2: // ARP Response
|
case 2: // ARP Response
|
||||||
|
@ -32,7 +32,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
const quint64 kBcastMac = 0xffffffffffffULL;
|
const quint64 kBcastMac = 0xffffffffffffULL;
|
||||||
|
|
||||||
// FIXME: add lock to protect deviceGroupList_ operations?
|
// XXX: Port owning DeviceManager already uses locks, so we don't use any
|
||||||
|
// locks within DeviceManager to protect deviceGroupList_ et.al.
|
||||||
|
|
||||||
DeviceManager::DeviceManager(AbstractPort *parent)
|
DeviceManager::DeviceManager(AbstractPort *parent)
|
||||||
{
|
{
|
||||||
@ -75,7 +76,7 @@ bool DeviceManager::addDeviceGroup(uint deviceGroupId)
|
|||||||
OstProto::DeviceGroup *deviceGroup;
|
OstProto::DeviceGroup *deviceGroup;
|
||||||
|
|
||||||
if (deviceGroupList_.contains(deviceGroupId)) {
|
if (deviceGroupList_.contains(deviceGroupId)) {
|
||||||
qWarning("%s: deviceGroup id %u already exists", __FUNCTION__,
|
qWarning("%s: deviceGroup id %u already exists", __FUNCTION__,
|
||||||
deviceGroupId);
|
deviceGroupId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -97,7 +98,7 @@ bool DeviceManager::deleteDeviceGroup(uint deviceGroupId)
|
|||||||
{
|
{
|
||||||
OstProto::DeviceGroup *deviceGroup;
|
OstProto::DeviceGroup *deviceGroup;
|
||||||
if (!deviceGroupList_.contains(deviceGroupId)) {
|
if (!deviceGroupList_.contains(deviceGroupId)) {
|
||||||
qWarning("%s: deviceGroup id %u does not exist", __FUNCTION__,
|
qWarning("%s: deviceGroup id %u does not exist", __FUNCTION__,
|
||||||
deviceGroupId);
|
deviceGroupId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -137,8 +138,6 @@ int DeviceManager::deviceCount()
|
|||||||
void DeviceManager::getDeviceList(
|
void DeviceManager::getDeviceList(
|
||||||
OstProto::PortDeviceList *deviceList)
|
OstProto::PortDeviceList *deviceList)
|
||||||
{
|
{
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
foreach(Device *device, deviceList_) {
|
foreach(Device *device, deviceList_) {
|
||||||
OstEmul::Device *dev =
|
OstEmul::Device *dev =
|
||||||
deviceList->AddExtension(OstEmul::port_device);
|
deviceList->AddExtension(OstEmul::port_device);
|
||||||
@ -160,7 +159,11 @@ void DeviceManager::receivePacket(PacketBuffer *pktBuf)
|
|||||||
// We assume pkt is ethernet
|
// We assume pkt is ethernet
|
||||||
// TODO: extend for other link layer types
|
// TODO: extend for other link layer types
|
||||||
|
|
||||||
// FIXME: validate before extracting if the offset is within pktLen
|
// All frames we are interested in should be at least 32 bytes
|
||||||
|
if (pktBuf->length() < 32) {
|
||||||
|
qWarning("short frame of %d bytes, skipping ...", pktBuf->length());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Extract dstMac
|
// Extract dstMac
|
||||||
dstMac = qFromBigEndian<quint32>(pktData + offset);
|
dstMac = qFromBigEndian<quint32>(pktData + offset);
|
||||||
|
@ -32,7 +32,7 @@ namespace OstProto {
|
|||||||
class DeviceGroup;
|
class DeviceGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeviceManager
|
class DeviceManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DeviceManager(AbstractPort *parent = 0);
|
DeviceManager(AbstractPort *parent = 0);
|
||||||
@ -66,7 +66,7 @@ private:
|
|||||||
void enumerateDevices(
|
void enumerateDevices(
|
||||||
const OstProto::DeviceGroup *deviceGroup,
|
const OstProto::DeviceGroup *deviceGroup,
|
||||||
Operation oper);
|
Operation oper);
|
||||||
|
|
||||||
AbstractPort *port_;
|
AbstractPort *port_;
|
||||||
QHash<uint, OstProto::DeviceGroup*> deviceGroupList_;
|
QHash<uint, OstProto::DeviceGroup*> deviceGroupList_;
|
||||||
QHash<DeviceKey, Device*> deviceList_;
|
QHash<DeviceKey, Device*> deviceList_;
|
||||||
|
@ -45,7 +45,7 @@ SOURCES += \
|
|||||||
winpcapport.cpp
|
winpcapport.cpp
|
||||||
SOURCES += myservice.cpp
|
SOURCES += myservice.cpp
|
||||||
SOURCES += pcapextra.cpp
|
SOURCES += pcapextra.cpp
|
||||||
SOURCES += packetbuffer.cpp
|
SOURCES += packetbuffer.cpp
|
||||||
|
|
||||||
QMAKE_DISTCLEAN += object_script.*
|
QMAKE_DISTCLEAN += object_script.*
|
||||||
|
|
||||||
|
@ -599,12 +599,15 @@ _invalid_version:
|
|||||||
done->Run();
|
done->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ===================================================================
|
* ===================================================================
|
||||||
* Device Emulation
|
* Device Emulation
|
||||||
* FIXME: Locking for these functions is at Port level, should it be
|
* ===================================================================
|
||||||
* moved to inside DeviceManager instead? In other words, are
|
* XXX: Streams and Devices are largely non-overlapping from a RPC
|
||||||
* streams/ports and devices independent?
|
* point of view but they *do* intersect e.g. when a stream is trying to
|
||||||
|
* find its associated device and info from that device such as src/dst
|
||||||
|
* mac addresses. For this reason, both set of RPCs share the common
|
||||||
|
* port level locking
|
||||||
* ===================================================================
|
* ===================================================================
|
||||||
*/
|
*/
|
||||||
void MyService::getDeviceGroupIdList(
|
void MyService::getDeviceGroupIdList(
|
||||||
@ -699,10 +702,8 @@ void MyService::addDeviceGroup(
|
|||||||
|
|
||||||
devMgr = portInfo[portId]->deviceManager();
|
devMgr = portInfo[portId]->deviceManager();
|
||||||
|
|
||||||
#if 0 // FIXME: needed?
|
|
||||||
if (portInfo[portId]->isTransmitOn())
|
if (portInfo[portId]->isTransmitOn())
|
||||||
goto _port_busy;
|
goto _port_busy;
|
||||||
#endif
|
|
||||||
|
|
||||||
portLock[portId]->lockForWrite();
|
portLock[portId]->lockForWrite();
|
||||||
for (int i = 0; i < request->device_group_id_size(); i++)
|
for (int i = 0; i < request->device_group_id_size(); i++)
|
||||||
@ -723,11 +724,9 @@ void MyService::addDeviceGroup(
|
|||||||
done->Run();
|
done->Run();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if 0 // FIXME: needed?
|
|
||||||
_port_busy:
|
_port_busy:
|
||||||
controller->SetFailed("Port Busy");
|
controller->SetFailed("Port Busy");
|
||||||
goto _exit;
|
goto _exit;
|
||||||
#endif
|
|
||||||
|
|
||||||
_invalid_port:
|
_invalid_port:
|
||||||
controller->SetFailed("invalid portid");
|
controller->SetFailed("invalid portid");
|
||||||
@ -752,10 +751,8 @@ void MyService::deleteDeviceGroup(
|
|||||||
|
|
||||||
devMgr = portInfo[portId]->deviceManager();
|
devMgr = portInfo[portId]->deviceManager();
|
||||||
|
|
||||||
#if 0 // FIXME: needed?
|
|
||||||
if (portInfo[portId]->isTransmitOn())
|
if (portInfo[portId]->isTransmitOn())
|
||||||
goto _port_busy;
|
goto _port_busy;
|
||||||
#endif
|
|
||||||
|
|
||||||
portLock[portId]->lockForWrite();
|
portLock[portId]->lockForWrite();
|
||||||
for (int i = 0; i < request->device_group_id_size(); i++)
|
for (int i = 0; i < request->device_group_id_size(); i++)
|
||||||
@ -767,11 +764,9 @@ void MyService::deleteDeviceGroup(
|
|||||||
done->Run();
|
done->Run();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if 0 // FIXME: needed?
|
|
||||||
_port_busy:
|
_port_busy:
|
||||||
controller->SetFailed("Port Busy");
|
controller->SetFailed("Port Busy");
|
||||||
goto _exit;
|
goto _exit;
|
||||||
#endif
|
|
||||||
_invalid_port:
|
_invalid_port:
|
||||||
controller->SetFailed("invalid portid");
|
controller->SetFailed("invalid portid");
|
||||||
_exit:
|
_exit:
|
||||||
@ -795,28 +790,22 @@ void MyService::modifyDeviceGroup(
|
|||||||
|
|
||||||
devMgr = portInfo[portId]->deviceManager();
|
devMgr = portInfo[portId]->deviceManager();
|
||||||
|
|
||||||
#if 0 // FIXME: needed?
|
|
||||||
if (portInfo[portId]->isTransmitOn())
|
if (portInfo[portId]->isTransmitOn())
|
||||||
goto _port_busy;
|
goto _port_busy;
|
||||||
#endif
|
|
||||||
|
|
||||||
portLock[portId]->lockForWrite();
|
portLock[portId]->lockForWrite();
|
||||||
for (int i = 0; i < request->device_group_size(); i++)
|
for (int i = 0; i < request->device_group_size(); i++)
|
||||||
devMgr->modifyDeviceGroup(&request->device_group(i));
|
devMgr->modifyDeviceGroup(&request->device_group(i));
|
||||||
portLock[portId]->unlock();
|
portLock[portId]->unlock();
|
||||||
|
|
||||||
// FIXME: check for overlaps between devices?
|
|
||||||
|
|
||||||
//! \todo(LOW): fill-in response "Ack"????
|
//! \todo(LOW): fill-in response "Ack"????
|
||||||
|
|
||||||
done->Run();
|
done->Run();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if 0 // FIXME: needed?
|
|
||||||
_port_busy:
|
_port_busy:
|
||||||
controller->SetFailed("Port Busy");
|
controller->SetFailed("Port Busy");
|
||||||
goto _exit;
|
goto _exit;
|
||||||
#endif
|
|
||||||
_invalid_port:
|
_invalid_port:
|
||||||
controller->SetFailed("invalid portid");
|
controller->SetFailed("invalid portid");
|
||||||
_exit:
|
_exit:
|
||||||
|
@ -84,7 +84,7 @@ PcapPort::PcapPort(int id, const char *device)
|
|||||||
monitorTx_ = new PortMonitor(device, kDirectionTx, &stats_);
|
monitorTx_ = new PortMonitor(device, kDirectionTx, &stats_);
|
||||||
transmitter_ = new PortTransmitter(device);
|
transmitter_ = new PortTransmitter(device);
|
||||||
capturer_ = new PortCapturer(device);
|
capturer_ = new PortCapturer(device);
|
||||||
receiver_ = new PortReceiver(device, deviceManager_);
|
emulXcvr_ = new EmulationTransceiver(device, deviceManager_);
|
||||||
|
|
||||||
if (!monitorRx_->handle() || !monitorTx_->handle())
|
if (!monitorRx_->handle() || !monitorTx_->handle())
|
||||||
isUsable_ = false;
|
isUsable_ = false;
|
||||||
@ -137,7 +137,7 @@ PcapPort::~PcapPort()
|
|||||||
if (monitorTx_)
|
if (monitorTx_)
|
||||||
monitorTx_->stop();
|
monitorTx_->stop();
|
||||||
|
|
||||||
delete receiver_;
|
delete emulXcvr_;
|
||||||
delete capturer_;
|
delete capturer_;
|
||||||
delete transmitter_;
|
delete transmitter_;
|
||||||
|
|
||||||
@ -174,17 +174,17 @@ void PcapPort::updateNotes()
|
|||||||
|
|
||||||
void PcapPort::startDeviceEmulation()
|
void PcapPort::startDeviceEmulation()
|
||||||
{
|
{
|
||||||
receiver_->start();
|
emulXcvr_->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapPort::stopDeviceEmulation()
|
void PcapPort::stopDeviceEmulation()
|
||||||
{
|
{
|
||||||
receiver_->stop();
|
emulXcvr_->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
int PcapPort::sendEmulationPacket(PacketBuffer *pktBuf)
|
int PcapPort::sendEmulationPacket(PacketBuffer *pktBuf)
|
||||||
{
|
{
|
||||||
return receiver_->transmitPacket(pktBuf);
|
return emulXcvr_->transmitPacket(pktBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -895,10 +895,10 @@ QFile* PcapPort::PortCapturer::captureFile()
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ------------------------------------------------------------------- *
|
* ------------------------------------------------------------------- *
|
||||||
* Port Receiver
|
* Transmit+Receiver for Device/ProtocolEmulation
|
||||||
* ------------------------------------------------------------------- *
|
* ------------------------------------------------------------------- *
|
||||||
*/
|
*/
|
||||||
PcapPort::PortReceiver::PortReceiver(const char *device,
|
PcapPort::EmulationTransceiver::EmulationTransceiver(const char *device,
|
||||||
DeviceManager *deviceManager)
|
DeviceManager *deviceManager)
|
||||||
{
|
{
|
||||||
device_ = QString::fromAscii(device);
|
device_ = QString::fromAscii(device);
|
||||||
@ -908,19 +908,19 @@ PcapPort::PortReceiver::PortReceiver(const char *device,
|
|||||||
handle_ = NULL;
|
handle_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PcapPort::PortReceiver::~PortReceiver()
|
PcapPort::EmulationTransceiver::~EmulationTransceiver()
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapPort::PortReceiver::run()
|
void PcapPort::EmulationTransceiver::run()
|
||||||
{
|
{
|
||||||
int flags = PCAP_OPENFLAG_PROMISCUOUS;
|
int flags = PCAP_OPENFLAG_PROMISCUOUS;
|
||||||
char errbuf[PCAP_ERRBUF_SIZE] = "";
|
char errbuf[PCAP_ERRBUF_SIZE] = "";
|
||||||
struct bpf_program bpf;
|
struct bpf_program bpf;
|
||||||
const char *capture_filter = "arp or (vlan and arp)";
|
const char *capture_filter = "arp or (vlan and arp)";
|
||||||
const int optimize = 1;
|
const int optimize = 1;
|
||||||
|
|
||||||
qDebug("In %s", __PRETTY_FUNCTION__);
|
qDebug("In %s", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
@ -931,10 +931,10 @@ _retry:
|
|||||||
// FIXME: use 0 timeout value?
|
// FIXME: use 0 timeout value?
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
// NOCAPTURE_LOCAL needs windows only pcap_open()
|
// NOCAPTURE_LOCAL needs windows only pcap_open()
|
||||||
handle_ = pcap_open(qPrintable(device_), 65535,
|
handle_ = pcap_open(qPrintable(device_), 65535,
|
||||||
flags, 1000 /* ms */, NULL, errbuf);
|
flags, 1000 /* ms */, NULL, errbuf);
|
||||||
#else
|
#else
|
||||||
handle_ = pcap_open_live(qPrintable(device_), 65535,
|
handle_ = pcap_open_live(qPrintable(device_), 65535,
|
||||||
flags, 1000 /* ms */, errbuf);
|
flags, 1000 /* ms */, errbuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -942,14 +942,12 @@ _retry:
|
|||||||
{
|
{
|
||||||
if (flags && QString(errbuf).contains("promiscuous"))
|
if (flags && QString(errbuf).contains("promiscuous"))
|
||||||
{
|
{
|
||||||
// FIXME: warn user that device emulation will not work
|
notify("Unable to set promiscuous mode on <%s> - "
|
||||||
qDebug("%s:can't set promiscuous mode, trying non-promisc",
|
"device emulation will not work", qPrintable(device_));
|
||||||
qPrintable(device_));
|
goto _exit;
|
||||||
flags &= ~PCAP_OPENFLAG_PROMISCUOUS;
|
|
||||||
goto _retry;
|
|
||||||
}
|
}
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
else if ((flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
|
else if ((flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
|
||||||
&& QString(errbuf).contains("loopback"))
|
&& QString(errbuf).contains("loopback"))
|
||||||
{
|
{
|
||||||
qDebug("Can't set no local capture mode %s", qPrintable(device_));
|
qDebug("Can't set no local capture mode %s", qPrintable(device_));
|
||||||
@ -959,22 +957,21 @@ _retry:
|
|||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// FIXME: warn user that device emulation will not work
|
notify("Unable to open <%s> [%s] - device emulation will not work",
|
||||||
qDebug("%s: Error opening port %s: %s\n", __FUNCTION__,
|
qPrintable(device_), errbuf);
|
||||||
device_.toAscii().constData(), errbuf);
|
|
||||||
goto _exit;
|
goto _exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: hardcoded filter
|
// FIXME: hardcoded filter
|
||||||
if (pcap_compile(handle_, &bpf, capture_filter, optimize, 0) < 0)
|
if (pcap_compile(handle_, &bpf, capture_filter, optimize, 0) < 0)
|
||||||
{
|
{
|
||||||
qWarning("%s: error compiling filter: %s", qPrintable(device_),
|
qWarning("%s: error compiling filter: %s", qPrintable(device_),
|
||||||
pcap_geterr(handle_));
|
pcap_geterr(handle_));
|
||||||
goto _skip_filter;
|
goto _skip_filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcap_setfilter(handle_, &bpf) < 0)
|
if (pcap_setfilter(handle_, &bpf) < 0)
|
||||||
{
|
{
|
||||||
qWarning("%s: error setting filter: %s", qPrintable(device_),
|
qWarning("%s: error setting filter: %s", qPrintable(device_),
|
||||||
pcap_geterr(handle_));
|
pcap_geterr(handle_));
|
||||||
@ -992,32 +989,32 @@ _skip_filter:
|
|||||||
ret = pcap_next_ex(handle_, &hdr, &data);
|
ret = pcap_next_ex(handle_, &hdr, &data);
|
||||||
switch (ret)
|
switch (ret)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
PacketBuffer *pktBuf = new PacketBuffer(data, hdr->caplen);
|
PacketBuffer *pktBuf = new PacketBuffer(data, hdr->caplen);
|
||||||
|
|
||||||
// XXX: deviceManager should free pktBuf before returning
|
// XXX: deviceManager should free pktBuf before returning
|
||||||
// from this call; if it needs to process the pkt async
|
// from this call; if it needs to process the pkt async
|
||||||
// it should make a copy as the pktBuf's data buffer is
|
// it should make a copy as the pktBuf's data buffer is
|
||||||
// owned by libpcap which does not guarantee data will
|
// owned by libpcap which does not guarantee data will
|
||||||
// persist across calls to pcap_next_ex()
|
// persist across calls to pcap_next_ex()
|
||||||
deviceManager_->receivePacket(pktBuf);
|
deviceManager_->receivePacket(pktBuf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0:
|
case 0:
|
||||||
// timeout: just go back to the loop
|
// timeout: just go back to the loop
|
||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
qWarning("%s: error reading packet (%d): %s",
|
qWarning("%s: error reading packet (%d): %s",
|
||||||
__PRETTY_FUNCTION__, ret, pcap_geterr(handle_));
|
__PRETTY_FUNCTION__, ret, pcap_geterr(handle_));
|
||||||
break;
|
break;
|
||||||
case -2:
|
case -2:
|
||||||
default:
|
default:
|
||||||
qFatal("%s: Unexpected return value %d", __PRETTY_FUNCTION__,
|
qFatal("%s: Unexpected return value %d", __PRETTY_FUNCTION__,
|
||||||
ret);
|
ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stop_)
|
if (stop_)
|
||||||
{
|
{
|
||||||
qDebug("user requested receiver stop\n");
|
qDebug("user requested receiver stop\n");
|
||||||
break;
|
break;
|
||||||
@ -1031,9 +1028,8 @@ _exit:
|
|||||||
state_ = kFinished;
|
state_ = kFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapPort::PortReceiver::start()
|
void PcapPort::EmulationTransceiver::start()
|
||||||
{
|
{
|
||||||
// FIXME: return error
|
|
||||||
if (state_ == kRunning) {
|
if (state_ == kRunning) {
|
||||||
qWarning("Receive start requested but is already running!");
|
qWarning("Receive start requested but is already running!");
|
||||||
return;
|
return;
|
||||||
@ -1046,7 +1042,7 @@ void PcapPort::PortReceiver::start()
|
|||||||
QThread::msleep(10);
|
QThread::msleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PcapPort::PortReceiver::stop()
|
void PcapPort::EmulationTransceiver::stop()
|
||||||
{
|
{
|
||||||
if (state_ == kRunning) {
|
if (state_ == kRunning) {
|
||||||
stop_ = true;
|
stop_ = true;
|
||||||
@ -1054,18 +1050,17 @@ void PcapPort::PortReceiver::stop()
|
|||||||
QThread::msleep(10);
|
QThread::msleep(10);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// FIXME: return error
|
|
||||||
qWarning("Receive stop requested but is not running!");
|
qWarning("Receive stop requested but is not running!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PcapPort::PortReceiver::isRunning()
|
bool PcapPort::EmulationTransceiver::isRunning()
|
||||||
{
|
{
|
||||||
return (state_ == kRunning);
|
return (state_ == kRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
int PcapPort::PortReceiver::transmitPacket(PacketBuffer *pktBuf)
|
int PcapPort::EmulationTransceiver::transmitPacket(PacketBuffer *pktBuf)
|
||||||
{
|
{
|
||||||
return pcap_sendpacket(handle_, pktBuf->data(), pktBuf->length());
|
return pcap_sendpacket(handle_, pktBuf->data(), pktBuf->length());
|
||||||
}
|
}
|
||||||
|
@ -225,12 +225,11 @@ protected:
|
|||||||
volatile State state_;
|
volatile State state_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: rename? not just a 'receiver' but also 'transmitter'!
|
class EmulationTransceiver: public QThread
|
||||||
class PortReceiver: public QThread
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PortReceiver(const char *device, DeviceManager *deviceManager);
|
EmulationTransceiver(const char *device, DeviceManager *deviceManager);
|
||||||
~PortReceiver();
|
~EmulationTransceiver();
|
||||||
void run();
|
void run();
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
@ -238,7 +237,7 @@ protected:
|
|||||||
int transmitPacket(PacketBuffer *pktBuf);
|
int transmitPacket(PacketBuffer *pktBuf);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum State
|
enum State
|
||||||
{
|
{
|
||||||
kNotStarted,
|
kNotStarted,
|
||||||
kRunning,
|
kRunning,
|
||||||
@ -260,7 +259,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
PortTransmitter *transmitter_;
|
PortTransmitter *transmitter_;
|
||||||
PortCapturer *capturer_;
|
PortCapturer *capturer_;
|
||||||
PortReceiver *receiver_;
|
EmulationTransceiver *emulXcvr_;
|
||||||
|
|
||||||
static pcap_if_t *deviceList_;
|
static pcap_if_t *deviceList_;
|
||||||
};
|
};
|
||||||
|
@ -23,7 +23,7 @@ use_defaults = False
|
|||||||
# initialize defaults - drone
|
# initialize defaults - drone
|
||||||
host_name = '127.0.0.1'
|
host_name = '127.0.0.1'
|
||||||
tx_port_number = -1
|
tx_port_number = -1
|
||||||
rx_port_number = -1
|
rx_port_number = -1
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
tshark = r'C:\Program Files\Wireshark\tshark.exe'
|
tshark = r'C:\Program Files\Wireshark\tshark.exe'
|
||||||
@ -94,7 +94,7 @@ try:
|
|||||||
sudo('sysctl -w net.ipv4.ip_forward=1')
|
sudo('sysctl -w net.ipv4.ip_forward=1')
|
||||||
|
|
||||||
# connect to drone
|
# connect to drone
|
||||||
log.info('connecting to drone(%s:%d)'
|
log.info('connecting to drone(%s:%d)'
|
||||||
% (drone.hostName(), drone.portNumber()))
|
% (drone.hostName(), drone.portNumber()))
|
||||||
drone.connect()
|
drone.connect()
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ try:
|
|||||||
print('---------')
|
print('---------')
|
||||||
for port in port_config_list.port:
|
for port in port_config_list.port:
|
||||||
print('%d.%s (%s)' % (port.port_id.id, port.name, port.description))
|
print('%d.%s (%s)' % (port.port_id.id, port.name, port.description))
|
||||||
# use a vhost port as default tx/rx port
|
# use a vhost port as default tx/rx port
|
||||||
if ('vhost' in port.name or 'sun' in port.description.lower()):
|
if ('vhost' in port.name or 'sun' in port.description.lower()):
|
||||||
if tx_port_number < 0:
|
if tx_port_number < 0:
|
||||||
tx_port_number = port.port_id.id
|
tx_port_number = port.port_id.id
|
||||||
@ -180,7 +180,7 @@ try:
|
|||||||
drone.addDeviceGroup(rx_dgid_list)
|
drone.addDeviceGroup(rx_dgid_list)
|
||||||
|
|
||||||
# ----------------------------------------------------------------- #
|
# ----------------------------------------------------------------- #
|
||||||
# create stream on tx port - each test case will modify and reuse
|
# create stream on tx port - each test case will modify and reuse
|
||||||
# this stream as per its needs
|
# this stream as per its needs
|
||||||
# ----------------------------------------------------------------- #
|
# ----------------------------------------------------------------- #
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ try:
|
|||||||
|
|
||||||
# ================================================================= #
|
# ================================================================= #
|
||||||
# ----------------------------------------------------------------- #
|
# ----------------------------------------------------------------- #
|
||||||
# TEST CASES
|
# TEST CASES
|
||||||
# ----------------------------------------------------------------- #
|
# ----------------------------------------------------------------- #
|
||||||
# ================================================================= #
|
# ================================================================= #
|
||||||
|
|
||||||
@ -280,10 +280,10 @@ try:
|
|||||||
ip = p.Extensions[ip4]
|
ip = p.Extensions[ip4]
|
||||||
ip.src_ip = 0x0a0a0165
|
ip.src_ip = 0x0a0a0165
|
||||||
ip.src_ip_mode = Ip4.e_im_inc_host
|
ip.src_ip_mode = Ip4.e_im_inc_host
|
||||||
ip.src_ip_count = num_devs
|
ip.src_ip_count = num_devs
|
||||||
ip.dst_ip = 0x0a0a0265
|
ip.dst_ip = 0x0a0a0265
|
||||||
ip.dst_ip_mode = Ip4.e_im_inc_host
|
ip.dst_ip_mode = Ip4.e_im_inc_host
|
||||||
ip.dst_ip_count = num_devs
|
ip.dst_ip_count = num_devs
|
||||||
|
|
||||||
s.protocol.add().protocol_id.id = ost_pb.Protocol.kUdpFieldNumber
|
s.protocol.add().protocol_id.id = ost_pb.Protocol.kUdpFieldNumber
|
||||||
s.protocol.add().protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber
|
s.protocol.add().protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber
|
||||||
@ -443,31 +443,31 @@ try:
|
|||||||
for i in range(num_vlans):
|
for i in range(num_vlans):
|
||||||
vlan_id = vlan_base+i
|
vlan_id = vlan_base+i
|
||||||
vrf = 'v' + str(vlan_id)
|
vrf = 'v' + str(vlan_id)
|
||||||
vlan_rx_dev = dut_rx_port + '.' + str(vlan_id)
|
vlan_rx_dev = dut_rx_port + '.' + str(vlan_id)
|
||||||
vlan_tx_dev = dut_tx_port + '.' + str(vlan_id)
|
vlan_tx_dev = dut_tx_port + '.' + str(vlan_id)
|
||||||
|
|
||||||
sudo('ip netns add ' + vrf)
|
sudo('ip netns add ' + vrf)
|
||||||
|
|
||||||
sudo('ip link add link ' + dut_rx_port
|
sudo('ip link add link ' + dut_rx_port
|
||||||
+ ' name ' + vlan_rx_dev
|
+ ' name ' + vlan_rx_dev
|
||||||
+ ' type vlan id ' + str(vlan_id))
|
+ ' type vlan id ' + str(vlan_id))
|
||||||
sudo('ip link set ' + vlan_rx_dev
|
sudo('ip link set ' + vlan_rx_dev
|
||||||
+ ' netns ' + vrf)
|
+ ' netns ' + vrf)
|
||||||
sudo('ip netns exec ' + vrf
|
sudo('ip netns exec ' + vrf
|
||||||
+ ' ip addr add 10.1.1.1/24'
|
+ ' ip addr add 10.1.1.1/24'
|
||||||
+ ' dev ' + vlan_rx_dev)
|
+ ' dev ' + vlan_rx_dev)
|
||||||
sudo('ip netns exec ' + vrf
|
sudo('ip netns exec ' + vrf
|
||||||
+ ' ip link set ' + vlan_rx_dev + ' up')
|
+ ' ip link set ' + vlan_rx_dev + ' up')
|
||||||
|
|
||||||
sudo('ip link add link ' + dut_tx_port
|
sudo('ip link add link ' + dut_tx_port
|
||||||
+ ' name ' + vlan_tx_dev
|
+ ' name ' + vlan_tx_dev
|
||||||
+ ' type vlan id ' + str(vlan_id))
|
+ ' type vlan id ' + str(vlan_id))
|
||||||
sudo('ip link set ' + vlan_tx_dev
|
sudo('ip link set ' + vlan_tx_dev
|
||||||
+ ' netns ' + vrf)
|
+ ' netns ' + vrf)
|
||||||
sudo('ip netns exec ' + vrf
|
sudo('ip netns exec ' + vrf
|
||||||
+ ' ip addr add 10.1.2.1/24'
|
+ ' ip addr add 10.1.2.1/24'
|
||||||
+ ' dev ' + vlan_tx_dev)
|
+ ' dev ' + vlan_tx_dev)
|
||||||
sudo('ip netns exec ' + vrf
|
sudo('ip netns exec ' + vrf
|
||||||
+ ' ip link set ' + vlan_tx_dev + ' up')
|
+ ' ip link set ' + vlan_tx_dev + ' up')
|
||||||
|
|
||||||
|
|
||||||
@ -510,7 +510,7 @@ try:
|
|||||||
|
|
||||||
# configure the tx stream(s)
|
# configure the tx stream(s)
|
||||||
# we need more than one stream, so delete old one
|
# we need more than one stream, so delete old one
|
||||||
# and create as many as we need
|
# and create as many as we need
|
||||||
# FIXME: restore the single stream at end?
|
# FIXME: restore the single stream at end?
|
||||||
log.info('deleting tx_stream %d' % stream_id.stream_id[0].id)
|
log.info('deleting tx_stream %d' % stream_id.stream_id[0].id)
|
||||||
drone.deleteStream(stream_id)
|
drone.deleteStream(stream_id)
|
||||||
@ -529,7 +529,7 @@ try:
|
|||||||
s = stream_cfg.stream.add()
|
s = stream_cfg.stream.add()
|
||||||
s.stream_id.id = stream_id.stream_id[i].id
|
s.stream_id.id = stream_id.stream_id[i].id
|
||||||
s.core.is_enabled = True
|
s.core.is_enabled = True
|
||||||
s.core.ordinal = i
|
s.core.ordinal = i
|
||||||
s.control.packets_per_sec = 10
|
s.control.packets_per_sec = 10
|
||||||
s.control.num_packets = num_devs
|
s.control.num_packets = num_devs
|
||||||
|
|
||||||
@ -572,14 +572,14 @@ try:
|
|||||||
for i in range(num_vlans):
|
for i in range(num_vlans):
|
||||||
vlan_id = vlan_base + i
|
vlan_id = vlan_base + i
|
||||||
vrf = 'v' + str(vlan_id)
|
vrf = 'v' + str(vlan_id)
|
||||||
vlan_rx_dev = dut_rx_port + '.' + str(vlan_id)
|
vlan_rx_dev = dut_rx_port + '.' + str(vlan_id)
|
||||||
vlan_tx_dev = dut_tx_port + '.' + str(vlan_id)
|
vlan_tx_dev = dut_tx_port + '.' + str(vlan_id)
|
||||||
|
|
||||||
sudo('ip netns exec ' + vrf
|
sudo('ip netns exec ' + vrf
|
||||||
+ ' ip neigh flush dev ' + vlan_rx_dev)
|
+ ' ip neigh flush dev ' + vlan_rx_dev)
|
||||||
sudo('ip netns exec ' + vrf
|
sudo('ip netns exec ' + vrf
|
||||||
+ ' ip neigh flush dev ' + vlan_tx_dev)
|
+ ' ip neigh flush dev ' + vlan_tx_dev)
|
||||||
sudo('ip netns exec ' + vrf
|
sudo('ip netns exec ' + vrf
|
||||||
+ ' ip neigh show')
|
+ ' ip neigh show')
|
||||||
|
|
||||||
drone.startCapture(rx_port)
|
drone.startCapture(rx_port)
|
||||||
@ -618,13 +618,13 @@ try:
|
|||||||
# show arp on DUT
|
# show arp on DUT
|
||||||
for i in range(num_vlans):
|
for i in range(num_vlans):
|
||||||
vrf = 'v' + str(vlan_base + i)
|
vrf = 'v' + str(vlan_base + i)
|
||||||
sudo('ip netns exec ' + vrf
|
sudo('ip netns exec ' + vrf
|
||||||
+ ' ip neigh show')
|
+ ' ip neigh show')
|
||||||
# un-configure the DUT
|
# un-configure the DUT
|
||||||
for i in range(num_vlans):
|
for i in range(num_vlans):
|
||||||
vlan_id = vlan_base + i
|
vlan_id = vlan_base + i
|
||||||
vrf = 'v' + str(vlan_id)
|
vrf = 'v' + str(vlan_id)
|
||||||
sudo('ip netns delete ' + vrf)
|
sudo('ip netns delete ' + vrf)
|
||||||
suite.test_end(passed)
|
suite.test_end(passed)
|
||||||
|
|
||||||
# TODO:
|
# TODO:
|
||||||
|
Loading…
Reference in New Issue
Block a user