Feature (contd.): Device Emulation - Mac protocol can now 'resolve' src/dst mac corresponding to the packet from the Device Emulation infra

This commit is contained in:
Srivats P 2015-11-10 19:40:32 +05:30
parent 0db170d393
commit 280d4bedaa
20 changed files with 323 additions and 106 deletions

View File

@ -49,3 +49,13 @@ void Stream::storeProtocolWidgets()
qWarning("%s: DOES NOTHING", __PRETTY_FUNCTION__); qWarning("%s: DOES NOTHING", __PRETTY_FUNCTION__);
return; return;
} }
quint64 getDeviceMacAddress(int portId, int streamId, int frameIndex)
{
return 0;
}
quint64 getNeighborMacAddress(int portId, int streamId, int frameIndex)
{
return 0;
}

View File

@ -19,6 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "mac.h" #include "mac.h"
#include "../common/streambase.h"
#include <QRegExp> #include <QRegExp>
#define uintToMacStr(num) \ #define uintToMacStr(num) \
@ -28,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
MacProtocol::MacProtocol(StreamBase *stream, AbstractProtocol *parent) MacProtocol::MacProtocol(StreamBase *stream, AbstractProtocol *parent)
: AbstractProtocol(stream, parent) : AbstractProtocol(stream, parent)
{ {
forResolve_ = false;
} }
MacProtocol::~MacProtocol() MacProtocol::~MacProtocol()
@ -124,6 +127,15 @@ QVariant MacProtocol::fieldData(int index, FieldAttrib attrib,
data.dst_mac_step(); data.dst_mac_step();
dstMac = data.dst_mac() - u; dstMac = data.dst_mac() - u;
break; break;
case OstProto::Mac::e_mm_resolve:
if (forResolve_)
dstMac = 0;
else {
forResolve_ = true;
dstMac = mpStream->neighborMacAddress(streamIndex);
forResolve_ = false;
}
break;
default: default:
qWarning("Unhandled dstMac_mode %d", data.dst_mac_mode()); qWarning("Unhandled dstMac_mode %d", data.dst_mac_mode());
} }
@ -169,6 +181,15 @@ QVariant MacProtocol::fieldData(int index, FieldAttrib attrib,
data.src_mac_step(); data.src_mac_step();
srcMac = data.src_mac() - u; srcMac = data.src_mac() - u;
break; break;
case OstProto::Mac::e_mm_resolve:
if (forResolve_)
srcMac = 0;
else {
forResolve_ = true;
srcMac = mpStream->deviceMacAddress(streamIndex);
forResolve_ = false;
}
break;
default: default:
qWarning("Unhandled srcMac_mode %d", data.src_mac_mode()); qWarning("Unhandled srcMac_mode %d", data.src_mac_mode());
} }
@ -331,11 +352,23 @@ int MacProtocol::protocolFrameVariableCount() const
{ {
int count = AbstractProtocol::protocolFrameVariableCount(); int count = AbstractProtocol::protocolFrameVariableCount();
if (data.dst_mac_mode() != OstProto::Mac::e_mm_fixed) switch (data.dst_mac_mode()) {
count = AbstractProtocol::lcm(count, data.dst_mac_count()); case OstProto::Mac::e_mm_inc:
case OstProto::Mac::e_mm_dec:
count = AbstractProtocol::lcm(count, data.dst_mac_count());
break;
default:
break;
}
if (data.src_mac_mode() != OstProto::Mac::e_mm_fixed) switch (data.src_mac_mode()) {
count = AbstractProtocol::lcm(count, data.src_mac_count()); case OstProto::Mac::e_mm_inc:
case OstProto::Mac::e_mm_dec:
count = AbstractProtocol::lcm(count, data.src_mac_count());
break;
default:
break;
}
return count; return count;
} }

View File

@ -67,6 +67,7 @@ public:
private: private:
OstProto::Mac data; OstProto::Mac data;
mutable bool forResolve_;
}; };
#endif #endif

View File

@ -28,6 +28,7 @@ message Mac {
e_mm_fixed = 0; e_mm_fixed = 0;
e_mm_inc = 1; e_mm_inc = 1;
e_mm_dec = 2; e_mm_dec = 2;
e_mm_resolve = 3; // dst: resolve neighbor; src: from device config
} }
// Dst Mac // Dst Mac

View File

@ -24,8 +24,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "protocolmanager.h" #include "protocolmanager.h"
extern ProtocolManager *OstProtocolManager; extern ProtocolManager *OstProtocolManager;
extern quint64 getDeviceMacAddress(int portId, int streamId, int frameIndex);
extern quint64 getNeighborMacAddress(int portId, int streamId, int frameIndex);
StreamBase::StreamBase() : StreamBase::StreamBase(int portId) :
portId_(portId),
mStreamId(new OstProto::StreamId), mStreamId(new OstProto::StreamId),
mCore(new OstProto::StreamCore), mCore(new OstProto::StreamCore),
mControl(new OstProto::StreamControl) mControl(new OstProto::StreamControl)
@ -537,6 +540,16 @@ int StreamBase::frameValue(uchar *buf, int bufMaxSize, int frameIndex) const
return pktLen; return pktLen;
} }
quint64 StreamBase::deviceMacAddress(int frameIndex) const
{
return getDeviceMacAddress(portId_, int(mStreamId->id()), frameIndex);
}
quint64 StreamBase::neighborMacAddress(int frameIndex) const
{
return getNeighborMacAddress(portId_, int(mStreamId->id()), frameIndex);
}
bool StreamBase::preflightCheck(QString &result) const bool StreamBase::preflightCheck(QString &result) const
{ {
bool pass = true; bool pass = true;

View File

@ -33,15 +33,8 @@ class ProtocolListIterator;
class StreamBase class StreamBase
{ {
private:
OstProto::StreamId *mStreamId;
OstProto::StreamCore *mCore;
OstProto::StreamControl *mControl;
ProtocolList *currentFrameProtocols;
public: public:
StreamBase(); StreamBase(int portId = -1);
~StreamBase(); ~StreamBase();
void protoDataCopyFrom(const OstProto::Stream &stream); void protoDataCopyFrom(const OstProto::Stream &stream);
@ -142,9 +135,22 @@ public:
int frameProtocolLength(int frameIndex) const; int frameProtocolLength(int frameIndex) const;
int frameCount() const; int frameCount() const;
int frameValue(uchar *buf, int bufMaxSize, int frameIndex) const; int frameValue(uchar *buf, int bufMaxSize, int frameIndex) const;
quint64 deviceMacAddress(int frameIndex) const;
quint64 neighborMacAddress(int frameIndex) const;
bool preflightCheck(QString &result) const; bool preflightCheck(QString &result) const;
static bool StreamLessThan(StreamBase* stream1, StreamBase* stream2); static bool StreamLessThan(StreamBase* stream1, StreamBase* stream2);
private:
int portId_;
OstProto::StreamId *mStreamId;
OstProto::StreamCore *mCore;
OstProto::StreamControl *mControl;
ProtocolList *currentFrameProtocols;
}; };
#endif #endif

View File

@ -573,9 +573,44 @@ void AbstractPort::updatePacketListInterleaved()
isSendQueueDirty_ = false; isSendQueueDirty_ = false;
} }
void AbstractPort::stats(PortStats *stats)
{
stats->rxPkts = (stats_.rxPkts >= epochStats_.rxPkts) ?
stats_.rxPkts - epochStats_.rxPkts :
stats_.rxPkts + (maxStatsValue_ - epochStats_.rxPkts);
stats->rxBytes = (stats_.rxBytes >= epochStats_.rxBytes) ?
stats_.rxBytes - epochStats_.rxBytes :
stats_.rxBytes + (maxStatsValue_ - epochStats_.rxBytes);
stats->rxPps = stats_.rxPps;
stats->rxBps = stats_.rxBps;
stats->txPkts = (stats_.txPkts >= epochStats_.txPkts) ?
stats_.txPkts - epochStats_.txPkts :
stats_.txPkts + (maxStatsValue_ - epochStats_.txPkts);
stats->txBytes = (stats_.txBytes >= epochStats_.txBytes) ?
stats_.txBytes - epochStats_.txBytes :
stats_.txBytes + (maxStatsValue_ - epochStats_.txBytes);
stats->txPps = stats_.txPps;
stats->txBps = stats_.txBps;
stats->rxDrops = (stats_.rxDrops >= epochStats_.rxDrops) ?
stats_.rxDrops - epochStats_.rxDrops :
stats_.rxDrops + (maxStatsValue_ - epochStats_.rxDrops);
stats->rxErrors = (stats_.rxErrors >= epochStats_.rxErrors) ?
stats_.rxErrors - epochStats_.rxErrors :
stats_.rxErrors + (maxStatsValue_ - epochStats_.rxErrors);
stats->rxFifoErrors = (stats_.rxFifoErrors >= epochStats_.rxFifoErrors) ?
stats_.rxFifoErrors - epochStats_.rxFifoErrors :
stats_.rxFifoErrors + (maxStatsValue_ - epochStats_.rxFifoErrors);
stats->rxFrameErrors = (stats_.rxFrameErrors >= epochStats_.rxFrameErrors) ?
stats_.rxFrameErrors - epochStats_.rxFrameErrors :
stats_.rxFrameErrors + (maxStatsValue_ - epochStats_.rxFrameErrors);
}
void AbstractPort::clearDeviceNeighbors() void AbstractPort::clearDeviceNeighbors()
{ {
deviceManager_->clearDeviceNeighbors(); deviceManager_->clearDeviceNeighbors();
isSendQueueDirty_ = true;
} }
void AbstractPort::resolveDeviceNeighbors() void AbstractPort::resolveDeviceNeighbors()
@ -596,48 +631,41 @@ void AbstractPort::resolveDeviceNeighbors()
int frameCount = stream->frameVariableCount(); int frameCount = stream->frameVariableCount();
for (int j = 0; j < frameCount; j++) { for (int j = 0; j < frameCount; j++) {
// TODO(optimization): we need the packet contents only uptil // we need the packet contents only uptil the L3 header
// the L3 header; it would be best if protocols/streams could int pktLen = stream->frameValue(pktBuf_, kMaxL3PktSize, j);
// cache the frameValue()
int pktLen = stream->frameValue(pktBuf_, sizeof(pktBuf_), j);
if (pktLen) { if (pktLen) {
PacketBuffer pktBuf(pktBuf_, pktLen); PacketBuffer pktBuf(pktBuf_, pktLen);
deviceManager_->resolveDeviceNeighbor(&pktBuf); deviceManager_->resolveDeviceNeighbor(&pktBuf);
} }
} }
} }
isSendQueueDirty_ = true;
} }
void AbstractPort::stats(PortStats *stats) quint64 AbstractPort::deviceMacAddress(int streamId, int frameIndex)
{ {
stats->rxPkts = (stats_.rxPkts >= epochStats_.rxPkts) ? // we need the packet contents only uptil the L3 header
stats_.rxPkts - epochStats_.rxPkts : StreamBase *s = stream(streamId);
stats_.rxPkts + (maxStatsValue_ - epochStats_.rxPkts); int pktLen = s->frameValue(pktBuf_, kMaxL3PktSize, frameIndex);
stats->rxBytes = (stats_.rxBytes >= epochStats_.rxBytes) ?
stats_.rxBytes - epochStats_.rxBytes :
stats_.rxBytes + (maxStatsValue_ - epochStats_.rxBytes);
stats->rxPps = stats_.rxPps;
stats->rxBps = stats_.rxBps;
stats->txPkts = (stats_.txPkts >= epochStats_.txPkts) ? if (pktLen) {
stats_.txPkts - epochStats_.txPkts : PacketBuffer pktBuf(pktBuf_, pktLen);
stats_.txPkts + (maxStatsValue_ - epochStats_.txPkts); return deviceManager_->deviceMacAddress(&pktBuf);
stats->txBytes = (stats_.txBytes >= epochStats_.txBytes) ? }
stats_.txBytes - epochStats_.txBytes :
stats_.txBytes + (maxStatsValue_ - epochStats_.txBytes);
stats->txPps = stats_.txPps;
stats->txBps = stats_.txBps;
stats->rxDrops = (stats_.rxDrops >= epochStats_.rxDrops) ? return 0;
stats_.rxDrops - epochStats_.rxDrops : }
stats_.rxDrops + (maxStatsValue_ - epochStats_.rxDrops);
stats->rxErrors = (stats_.rxErrors >= epochStats_.rxErrors) ? quint64 AbstractPort::neighborMacAddress(int streamId, int frameIndex)
stats_.rxErrors - epochStats_.rxErrors : {
stats_.rxErrors + (maxStatsValue_ - epochStats_.rxErrors); // we need the packet contents only uptil the L3 header
stats->rxFifoErrors = (stats_.rxFifoErrors >= epochStats_.rxFifoErrors) ? StreamBase *s = stream(streamId);
stats_.rxFifoErrors - epochStats_.rxFifoErrors : int pktLen = s->frameValue(pktBuf_, kMaxL3PktSize, frameIndex);
stats_.rxFifoErrors + (maxStatsValue_ - epochStats_.rxFifoErrors);
stats->rxFrameErrors = (stats_.rxFrameErrors >= epochStats_.rxFrameErrors) ? if (pktLen) {
stats_.rxFrameErrors - epochStats_.rxFrameErrors : PacketBuffer pktBuf(pktBuf_, pktLen);
stats_.rxFrameErrors + (maxStatsValue_ - epochStats_.rxFrameErrors); return deviceManager_->neighborMacAddress(&pktBuf);
}
return 0;
} }

View File

@ -95,6 +95,9 @@ public:
virtual bool isCaptureOn() = 0; virtual bool isCaptureOn() = 0;
virtual QIODevice* captureData() = 0; virtual QIODevice* captureData() = 0;
void stats(PortStats *stats);
void resetStats() { epochStats_ = stats_; }
DeviceManager* deviceManager(); DeviceManager* deviceManager();
virtual void startDeviceEmulation() = 0; virtual void startDeviceEmulation() = 0;
virtual void stopDeviceEmulation() = 0; virtual void stopDeviceEmulation() = 0;
@ -103,8 +106,8 @@ public:
void clearDeviceNeighbors(); void clearDeviceNeighbors();
void resolveDeviceNeighbors(); void resolveDeviceNeighbors();
void stats(PortStats *stats); quint64 deviceMacAddress(int streamId, int frameIndex);
void resetStats() { epochStats_ = stats_; } quint64 neighborMacAddress(int streamId, int frameIndex);
protected: protected:
void addNote(QString note); void addNote(QString note);
@ -129,6 +132,12 @@ private:
static const int kMaxPktSize = 16384; static const int kMaxPktSize = 16384;
uchar pktBuf_[kMaxPktSize]; uchar pktBuf_[kMaxPktSize];
// When finding a corresponding device for a packet, we need to inspect
// only uptil the L3 header; in the worst case this would be -
// mac (12) + 4 x vlan (16) + ethType (2) + ipv6 (40) = 74 bytes
// let's round it up to 80 bytes
static const int kMaxL3PktSize = 80;
/*! \note StreamBase::id() and index into streamList[] are NOT same! */ /*! \note StreamBase::id() and index into streamList[] are NOT same! */
QList<StreamBase*> streamList_; QList<StreamBase*> streamList_;

View File

@ -72,6 +72,11 @@ void Device::setVlan(int index, quint16 vlan)
numVlanTags_ = index + 1; numVlanTags_ = index + 1;
} }
quint64 Device::mac()
{
return mac_;
}
void Device::setMac(quint64 mac) void Device::setMac(quint64 mac)
{ {
int ofs = kMaxVlan * sizeof(quint16); int ofs = kMaxVlan * sizeof(quint16);
@ -215,6 +220,65 @@ void Device::getNeighbors(OstEmul::DeviceNeighbors *neighbors)
} }
} }
// We expect pktBuf to point to EthType on entry
bool Device::isOrigin(const PacketBuffer *pktBuf)
{
const uchar *pktData = pktBuf->data();
quint16 ethType = qFromBigEndian<quint16>(pktData);
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
pktData += 2;
// We know only about IP packets
if (ethType == 0x0800) { // IPv4
int ipHdrLen = (pktData[0] & 0x0F) << 2;
quint32 srcIp;
if (pktBuf->length() < ipHdrLen) {
qDebug("incomplete IPv4 header: expected %d, actual %d",
ipHdrLen, pktBuf->length());
return false;
}
srcIp = qFromBigEndian<quint32>(pktData + ipHdrLen - 8);
qDebug("%s: pktSrcIp/selfIp = 0x%x/0x%x", __FUNCTION__, srcIp, ip4_);
return (srcIp == ip4_);
}
return false;
}
// We expect pktBuf to point to EthType on entry
quint64 Device::neighborMac(const PacketBuffer *pktBuf)
{
const uchar *pktData = pktBuf->data();
quint16 ethType = qFromBigEndian<quint16>(pktData);
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
pktData += 2;
// We know only about IP packets
if (ethType == 0x0800) { // IPv4
int ipHdrLen = (pktData[0] & 0x0F) << 2;
quint32 dstIp, tgtIp, mask;
if (pktBuf->length() < ipHdrLen) {
qDebug("incomplete IPv4 header: expected %d, actual %d",
ipHdrLen, pktBuf->length());
return false;
}
dstIp = qFromBigEndian<quint32>(pktData + ipHdrLen - 4);
mask = ~0 << (32 - ip4PrefixLength_);
qDebug("dst %x self %x mask %x", dstIp, ip4_, mask);
tgtIp = ((dstIp & mask) == (ip4_ & mask)) ? dstIp : ip4Gateway_;
return arpTable.value(tgtIp);
}
return false;
}
// //
// Private Methods // Private Methods
// //
@ -348,13 +412,15 @@ void Device::sendArpRequest(PacketBuffer *pktBuf)
dstIp = qFromBigEndian<quint32>(pktData + ipHdrLen - 4); dstIp = qFromBigEndian<quint32>(pktData + ipHdrLen - 4);
// TODO: if we have already sent a ARP request for the dst IP, do not
// resend - requires some sort of state per entry (timeout also?)
mask = ~0 << (32 - ip4PrefixLength_); mask = ~0 << (32 - ip4PrefixLength_);
qDebug("dst %x src %x mask %x", dstIp, srcIp, mask); qDebug("dst %x src %x mask %x", dstIp, srcIp, mask);
tgtIp = ((dstIp & mask) == (srcIp & mask)) ? dstIp : ip4Gateway_; tgtIp = ((dstIp & mask) == (srcIp & mask)) ? dstIp : ip4Gateway_;
// Do we already have a ARP entry (resolved or unresolved)?
// FIXME: do we need a timer to resend ARP for unresolved entries?
if (arpTable.contains(tgtIp))
return;
reqPkt = new PacketBuffer; reqPkt = new PacketBuffer;
reqPkt->reserve(encapSize()); reqPkt->reserve(encapSize());
pktData = reqPkt->put(28); pktData = reqPkt->put(28);
@ -375,6 +441,7 @@ void Device::sendArpRequest(PacketBuffer *pktBuf)
encap(reqPkt, kBcastMac, 0x0806); encap(reqPkt, kBcastMac, 0x0806);
transmitPacket(reqPkt); transmitPacket(reqPkt);
arpTable.insert(tgtIp, 0);
qDebug("Sent ARP Request for srcIp/tgtIp=%s/%s", qDebug("Sent ARP Request for srcIp/tgtIp=%s/%s",
qPrintable(QHostAddress(srcIp).toString()), qPrintable(QHostAddress(srcIp).toString()),

View File

@ -37,6 +37,7 @@ public:
Device(DeviceManager *deviceManager); Device(DeviceManager *deviceManager);
void setVlan(int index, quint16 vlan); void setVlan(int index, quint16 vlan);
quint64 mac();
void setMac(quint64 mac); void setMac(quint64 mac);
void setIp4(quint32 address, int prefixLength, quint32 gateway); void setIp4(quint32 address, int prefixLength, quint32 gateway);
QString config(); QString config();
@ -54,6 +55,9 @@ public:
void resolveNeighbor(PacketBuffer *pktBuf); void resolveNeighbor(PacketBuffer *pktBuf);
void getNeighbors(OstEmul::DeviceNeighbors *neighbors); void getNeighbors(OstEmul::DeviceNeighbors *neighbors);
bool isOrigin(const PacketBuffer *pktBuf);
quint64 neighborMac(const PacketBuffer *pktBuf);
private: // methods private: // methods
void receiveArp(PacketBuffer *pktBuf); void receiveArp(PacketBuffer *pktBuf);
void sendArpRequest(PacketBuffer *pktBuf); void sendArpRequest(PacketBuffer *pktBuf);

View File

@ -227,36 +227,47 @@ void DeviceManager::getDeviceNeighbors(
} }
} }
// FIXME: This function is mostly a duplicate of receivePacket;
// can we have a single combined one?
void DeviceManager::resolveDeviceNeighbor(PacketBuffer *pktBuf) void DeviceManager::resolveDeviceNeighbor(PacketBuffer *pktBuf)
{
Device *device = originDevice(pktBuf);
if (device)
device->resolveNeighbor(pktBuf);
}
quint64 DeviceManager::deviceMacAddress(PacketBuffer *pktBuf)
{
Device *device = originDevice(pktBuf);
return device ? device->mac() : 0;
}
quint64 DeviceManager::neighborMacAddress(PacketBuffer *pktBuf)
{
Device *device = originDevice(pktBuf);
return device ? device->neighborMac(pktBuf) : 0;
}
// ------------------------------------ //
// Private Methods
// ------------------------------------ //
Device* DeviceManager::originDevice(PacketBuffer *pktBuf)
{ {
uchar *pktData = pktBuf->data(); uchar *pktData = pktBuf->data();
int offset = 0; int offset = 12; // start parsing after mac addresses
Device dk(this); Device dk(this);
Device *device;
quint64 dstMac = kBcastMac;
quint16 ethType; quint16 ethType;
quint16 vlan; quint16 vlan;
int idx = 0; int idx = 0;
// NOTE: // pktBuf will not have the correct dstMac populated, so use bcastMac
// 1. Since resolution hasn't happened yet, dstMac will not be valid; // and search for device by IP
// so we use the Bcast address instead
// 2. We assume pkt is ethernet; TODO: extend for other link layer types
// FIXME: validate before extracting if the offset is within pktLen dk.setMac(kBcastMac);
dk.setMac(dstMac);
offset += 6;
// Skip srcMac - don't care
offset += 6;
qDebug("dstMac %012" PRIx64, dstMac);
_eth_type: _eth_type:
// Extract EthType
ethType = qFromBigEndian<quint16>(pktData + offset); ethType = qFromBigEndian<quint16>(pktData + offset);
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType); qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
@ -271,29 +282,13 @@ _eth_type:
pktBuf->pull(offset); pktBuf->pull(offset);
if (dstMac == kBcastMac) { foreach(Device *device, bcastList_.values(dk.key())) {
QList<Device*> list = bcastList_.values(dk.key()); if (device->isOrigin(pktBuf))
// FIXME: We need to clone the pktBuf before passing to each return device;
// device, otherwise only the first device gets the original
// packet - all subsequent ones get the modified packet!
// NOTE: modification may not be in the pkt data buffer but
// in the HDTE pointers - which is bad as well!
foreach(Device *device, list)
device->resolveNeighbor(pktBuf);
goto _exit;
} }
// Is it destined for us? qDebug("couldn't find origin device for packet");
device = deviceList_.value(dk.key()); return NULL;
if (!device) {
qDebug("%s: dstMac %012llx is not us", __FUNCTION__, dstMac);
goto _exit;
}
device->receivePacket(pktBuf);
_exit:
return;
} }
void DeviceManager::enumerateDevices( void DeviceManager::enumerateDevices(

View File

@ -55,9 +55,12 @@ public:
void resolveDeviceNeighbor(PacketBuffer *pktBuf); void resolveDeviceNeighbor(PacketBuffer *pktBuf);
void getDeviceNeighbors(OstProto::DeviceNeighborList *neighborList); void getDeviceNeighbors(OstProto::DeviceNeighborList *neighborList);
quint64 deviceMacAddress(PacketBuffer *pktBuf);
quint64 neighborMacAddress(PacketBuffer *pktBuf);
private: private:
enum Operation { kAdd, kDelete }; enum Operation { kAdd, kDelete };
Device* originDevice(PacketBuffer *pktBuf);
void enumerateDevices( void enumerateDevices(
const OstProto::DeviceGroup *deviceGroup, const OstProto::DeviceGroup *deviceGroup,
Operation oper); Operation oper);

View File

@ -58,3 +58,8 @@ bool Drone::init()
return true; return true;
} }
MyService* Drone::rpcService()
{
return service;
}

View File

@ -32,6 +32,7 @@ public:
Drone(QObject *parent = 0); Drone(QObject *parent = 0);
~Drone(); ~Drone();
bool init(); bool init();
MyService* rpcService();
private: private:
RpcServer *rpcServer; RpcServer *rpcServer;

View File

@ -35,6 +35,7 @@ extern ProtocolManager *OstProtocolManager;
extern char *version; extern char *version;
extern char *revision; extern char *revision;
Drone *drone;
QSettings *appSettings; QSettings *appSettings;
int myport; int myport;
@ -47,7 +48,6 @@ int main(int argc, char *argv[])
{ {
int exitCode = 0; int exitCode = 0;
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
Drone *drone;
// TODO: command line options // TODO: command line options
// -v (--version) // -v (--version)

View File

@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "myservice.h" #include "myservice.h"
#include "drone.h"
#if 0 #if 0
#include <qglobal.h> #include <qglobal.h>
#include <qendian.h> #include <qendian.h>
@ -38,6 +40,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include <QStringList> #include <QStringList>
extern Drone *drone;
extern char *version; extern char *version;
MyService::MyService() MyService::MyService()
@ -241,7 +244,7 @@ void MyService::addStream(::google::protobuf::RpcController* controller,
// Append a new "default" stream - actual contents of the new stream is // Append a new "default" stream - actual contents of the new stream is
// expected in a subsequent "modifyStream" request - set the stream id // expected in a subsequent "modifyStream" request - set the stream id
// now itself however!!! // now itself however!!!
stream = new StreamBase; stream = new StreamBase(portId);
stream->setId(request->stream_id(i).id()); stream->setId(request->stream_id(i).id());
portInfo[portId]->addStream(stream); portInfo[portId]->addStream(stream);
} }
@ -360,6 +363,8 @@ void MyService::startTransmit(::google::protobuf::RpcController* /*controller*/,
continue; //! \todo (LOW): partial RPC? continue; //! \todo (LOW): partial RPC?
portLock[portId]->lockForWrite(); portLock[portId]->lockForWrite();
if (portInfo[portId]->isDirty())
portInfo[portId]->updatePacketList();
portInfo[portId]->startTransmit(); portInfo[portId]->startTransmit();
portLock[portId]->unlock(); portLock[portId]->unlock();
} }
@ -899,3 +904,33 @@ _invalid_port:
controller->SetFailed("Invalid Port Id"); controller->SetFailed("Invalid Port Id");
done->Run(); done->Run();
} }
quint64 getDeviceMacAddress(int portId, int streamId, int frameIndex)
{
MyService *service = drone->rpcService();
quint64 mac;
if (!service)
return 0;
service->portLock[portId]->lockForWrite();
mac = service->portInfo[portId]->deviceMacAddress(streamId, frameIndex);
service->portLock[portId]->unlock();
return mac;
}
quint64 getNeighborMacAddress(int portId, int streamId, int frameIndex)
{
MyService *service = drone->rpcService();
quint64 mac;
if (!service)
return 0;
service->portLock[portId]->lockForWrite();
mac = service->portInfo[portId]->neighborMacAddress(streamId, frameIndex);
service->portLock[portId]->unlock();
return mac;
}

View File

@ -147,6 +147,11 @@ public:
const ::OstProto::PortId* request, const ::OstProto::PortId* request,
::OstProto::DeviceNeighborList* response, ::OstProto::DeviceNeighborList* response,
::google::protobuf::Closure* done); ::google::protobuf::Closure* done);
friend quint64 getDeviceMacAddress(
int portId, int streamId, int frameIndex);
friend quint64 getNeighborMacAddress(
int portId, int streamId, int frameIndex);
signals: signals:
void notification(int notifType, SharedProtobufMessage notifData); void notification(int notifType, SharedProtobufMessage notifData);

View File

@ -49,27 +49,27 @@ PacketBuffer::~PacketBuffer()
delete[] buffer_; delete[] buffer_;
} }
int PacketBuffer::length() int PacketBuffer::length() const
{ {
return tail_ - data_; return tail_ - data_;
} }
uchar* PacketBuffer::head() uchar* PacketBuffer::head() const
{ {
return head_; return head_;
} }
uchar* PacketBuffer::data() uchar* PacketBuffer::data() const
{ {
return data_; return data_;
} }
uchar* PacketBuffer::tail() uchar* PacketBuffer::tail() const
{ {
return tail_; return tail_;
} }
uchar* PacketBuffer::end() uchar* PacketBuffer::end() const
{ {
return end_; return end_;
} }

View File

@ -29,12 +29,12 @@ public:
PacketBuffer(const uchar *buffer, int size); PacketBuffer(const uchar *buffer, int size);
~PacketBuffer(); ~PacketBuffer();
int length(); int length() const;
uchar* head(); uchar* head() const;
uchar* data(); uchar* data() const;
uchar* tail(); uchar* tail() const;
uchar* end(); uchar* end() const;
void reserve(int len); void reserve(int len);
uchar* pull(int len); uchar* pull(int len);

View File

@ -14,7 +14,7 @@ from harness import Test, TestSuite, TestPreRequisiteError
sys.path.insert(1, '../binding') sys.path.insert(1, '../binding')
from core import ost_pb, emul, DroneProxy from core import ost_pb, emul, DroneProxy
from rpc import RpcError from rpc import RpcError
from protocols.mac_pb2 import mac from protocols.mac_pb2 import mac, Mac
from protocols.ip4_pb2 import ip4, Ip4 from protocols.ip4_pb2 import ip4, Ip4
from protocols.vlan_pb2 import vlan from protocols.vlan_pb2 import vlan
@ -263,8 +263,8 @@ try:
# setup stream protocols as mac:eth2:ip4:udp:payload # setup stream protocols as mac:eth2:ip4:udp:payload
p = s.protocol.add() p = s.protocol.add()
p.protocol_id.id = ost_pb.Protocol.kMacFieldNumber p.protocol_id.id = ost_pb.Protocol.kMacFieldNumber
p.Extensions[mac].dst_mac = dut_dst_mac p.Extensions[mac].dst_mac_mode = Mac.e_mm_resolve
p.Extensions[mac].src_mac = 0x00aabbccddee p.Extensions[mac].src_mac_mode = Mac.e_mm_resolve
p = s.protocol.add() p = s.protocol.add()
p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber
@ -401,6 +401,7 @@ try:
sudo('ip address delete 10.10.2.1/24 dev ' + dut_tx_port) sudo('ip address delete 10.10.2.1/24 dev ' + dut_tx_port)
suite.test_end(passed) suite.test_end(passed)
sys.exit(1)
# FIXME: update the below test cases to resolve Neighbors and streams # FIXME: update the below test cases to resolve Neighbors and streams
# to derive src/dst mac from device # to derive src/dst mac from device