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:
parent
0db170d393
commit
280d4bedaa
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
OstProto::Mac data;
|
OstProto::Mac data;
|
||||||
|
mutable bool forResolve_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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_;
|
||||||
|
|
||||||
|
@ -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()),
|
||||||
|
@ -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);
|
||||||
|
@ -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(
|
||||||
|
@ -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);
|
||||||
|
@ -58,3 +58,8 @@ bool Drone::init()
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MyService* Drone::rpcService()
|
||||||
|
{
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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_;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user