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__);
|
||||
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 "../common/streambase.h"
|
||||
|
||||
#include <QRegExp>
|
||||
|
||||
#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)
|
||||
: AbstractProtocol(stream, parent)
|
||||
{
|
||||
forResolve_ = false;
|
||||
}
|
||||
|
||||
MacProtocol::~MacProtocol()
|
||||
@ -124,6 +127,15 @@ QVariant MacProtocol::fieldData(int index, FieldAttrib attrib,
|
||||
data.dst_mac_step();
|
||||
dstMac = data.dst_mac() - u;
|
||||
break;
|
||||
case OstProto::Mac::e_mm_resolve:
|
||||
if (forResolve_)
|
||||
dstMac = 0;
|
||||
else {
|
||||
forResolve_ = true;
|
||||
dstMac = mpStream->neighborMacAddress(streamIndex);
|
||||
forResolve_ = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qWarning("Unhandled dstMac_mode %d", data.dst_mac_mode());
|
||||
}
|
||||
@ -169,6 +181,15 @@ QVariant MacProtocol::fieldData(int index, FieldAttrib attrib,
|
||||
data.src_mac_step();
|
||||
srcMac = data.src_mac() - u;
|
||||
break;
|
||||
case OstProto::Mac::e_mm_resolve:
|
||||
if (forResolve_)
|
||||
srcMac = 0;
|
||||
else {
|
||||
forResolve_ = true;
|
||||
srcMac = mpStream->deviceMacAddress(streamIndex);
|
||||
forResolve_ = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qWarning("Unhandled srcMac_mode %d", data.src_mac_mode());
|
||||
}
|
||||
@ -331,11 +352,23 @@ int MacProtocol::protocolFrameVariableCount() const
|
||||
{
|
||||
int count = AbstractProtocol::protocolFrameVariableCount();
|
||||
|
||||
if (data.dst_mac_mode() != OstProto::Mac::e_mm_fixed)
|
||||
count = AbstractProtocol::lcm(count, data.dst_mac_count());
|
||||
switch (data.dst_mac_mode()) {
|
||||
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)
|
||||
count = AbstractProtocol::lcm(count, data.src_mac_count());
|
||||
switch (data.src_mac_mode()) {
|
||||
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;
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ public:
|
||||
|
||||
private:
|
||||
OstProto::Mac data;
|
||||
mutable bool forResolve_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -28,6 +28,7 @@ message Mac {
|
||||
e_mm_fixed = 0;
|
||||
e_mm_inc = 1;
|
||||
e_mm_dec = 2;
|
||||
e_mm_resolve = 3; // dst: resolve neighbor; src: from device config
|
||||
}
|
||||
|
||||
// Dst Mac
|
||||
|
@ -24,8 +24,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include "protocolmanager.h"
|
||||
|
||||
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),
|
||||
mCore(new OstProto::StreamCore),
|
||||
mControl(new OstProto::StreamControl)
|
||||
@ -537,6 +540,16 @@ int StreamBase::frameValue(uchar *buf, int bufMaxSize, int frameIndex) const
|
||||
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 pass = true;
|
||||
|
@ -33,15 +33,8 @@ class ProtocolListIterator;
|
||||
|
||||
class StreamBase
|
||||
{
|
||||
private:
|
||||
OstProto::StreamId *mStreamId;
|
||||
OstProto::StreamCore *mCore;
|
||||
OstProto::StreamControl *mControl;
|
||||
|
||||
ProtocolList *currentFrameProtocols;
|
||||
|
||||
public:
|
||||
StreamBase();
|
||||
StreamBase(int portId = -1);
|
||||
~StreamBase();
|
||||
|
||||
void protoDataCopyFrom(const OstProto::Stream &stream);
|
||||
@ -142,9 +135,22 @@ public:
|
||||
int frameProtocolLength(int frameIndex) const;
|
||||
int frameCount() 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;
|
||||
|
||||
static bool StreamLessThan(StreamBase* stream1, StreamBase* stream2);
|
||||
|
||||
private:
|
||||
int portId_;
|
||||
|
||||
OstProto::StreamId *mStreamId;
|
||||
OstProto::StreamCore *mCore;
|
||||
OstProto::StreamControl *mControl;
|
||||
|
||||
ProtocolList *currentFrameProtocols;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -573,9 +573,44 @@ void AbstractPort::updatePacketListInterleaved()
|
||||
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()
|
||||
{
|
||||
deviceManager_->clearDeviceNeighbors();
|
||||
isSendQueueDirty_ = true;
|
||||
}
|
||||
|
||||
void AbstractPort::resolveDeviceNeighbors()
|
||||
@ -596,48 +631,41 @@ void AbstractPort::resolveDeviceNeighbors()
|
||||
int frameCount = stream->frameVariableCount();
|
||||
|
||||
for (int j = 0; j < frameCount; j++) {
|
||||
// TODO(optimization): we need the packet contents only uptil
|
||||
// the L3 header; it would be best if protocols/streams could
|
||||
// cache the frameValue()
|
||||
int pktLen = stream->frameValue(pktBuf_, sizeof(pktBuf_), j);
|
||||
// we need the packet contents only uptil the L3 header
|
||||
int pktLen = stream->frameValue(pktBuf_, kMaxL3PktSize, j);
|
||||
if (pktLen) {
|
||||
PacketBuffer pktBuf(pktBuf_, pktLen);
|
||||
deviceManager_->resolveDeviceNeighbor(&pktBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
isSendQueueDirty_ = true;
|
||||
}
|
||||
|
||||
void AbstractPort::stats(PortStats *stats)
|
||||
quint64 AbstractPort::deviceMacAddress(int streamId, int frameIndex)
|
||||
{
|
||||
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;
|
||||
// we need the packet contents only uptil the L3 header
|
||||
StreamBase *s = stream(streamId);
|
||||
int pktLen = s->frameValue(pktBuf_, kMaxL3PktSize, frameIndex);
|
||||
|
||||
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;
|
||||
if (pktLen) {
|
||||
PacketBuffer pktBuf(pktBuf_, pktLen);
|
||||
return deviceManager_->deviceMacAddress(&pktBuf);
|
||||
}
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
quint64 AbstractPort::neighborMacAddress(int streamId, int frameIndex)
|
||||
{
|
||||
// we need the packet contents only uptil the L3 header
|
||||
StreamBase *s = stream(streamId);
|
||||
int pktLen = s->frameValue(pktBuf_, kMaxL3PktSize, frameIndex);
|
||||
|
||||
if (pktLen) {
|
||||
PacketBuffer pktBuf(pktBuf_, pktLen);
|
||||
return deviceManager_->neighborMacAddress(&pktBuf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -95,6 +95,9 @@ public:
|
||||
virtual bool isCaptureOn() = 0;
|
||||
virtual QIODevice* captureData() = 0;
|
||||
|
||||
void stats(PortStats *stats);
|
||||
void resetStats() { epochStats_ = stats_; }
|
||||
|
||||
DeviceManager* deviceManager();
|
||||
virtual void startDeviceEmulation() = 0;
|
||||
virtual void stopDeviceEmulation() = 0;
|
||||
@ -103,8 +106,8 @@ public:
|
||||
void clearDeviceNeighbors();
|
||||
void resolveDeviceNeighbors();
|
||||
|
||||
void stats(PortStats *stats);
|
||||
void resetStats() { epochStats_ = stats_; }
|
||||
quint64 deviceMacAddress(int streamId, int frameIndex);
|
||||
quint64 neighborMacAddress(int streamId, int frameIndex);
|
||||
|
||||
protected:
|
||||
void addNote(QString note);
|
||||
@ -129,6 +132,12 @@ private:
|
||||
static const int kMaxPktSize = 16384;
|
||||
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! */
|
||||
QList<StreamBase*> streamList_;
|
||||
|
||||
|
@ -72,6 +72,11 @@ void Device::setVlan(int index, quint16 vlan)
|
||||
numVlanTags_ = index + 1;
|
||||
}
|
||||
|
||||
quint64 Device::mac()
|
||||
{
|
||||
return mac_;
|
||||
}
|
||||
|
||||
void Device::setMac(quint64 mac)
|
||||
{
|
||||
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
|
||||
//
|
||||
@ -348,13 +412,15 @@ void Device::sendArpRequest(PacketBuffer *pktBuf)
|
||||
|
||||
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_);
|
||||
qDebug("dst %x src %x mask %x", dstIp, srcIp, mask);
|
||||
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->reserve(encapSize());
|
||||
pktData = reqPkt->put(28);
|
||||
@ -375,6 +441,7 @@ void Device::sendArpRequest(PacketBuffer *pktBuf)
|
||||
|
||||
encap(reqPkt, kBcastMac, 0x0806);
|
||||
transmitPacket(reqPkt);
|
||||
arpTable.insert(tgtIp, 0);
|
||||
|
||||
qDebug("Sent ARP Request for srcIp/tgtIp=%s/%s",
|
||||
qPrintable(QHostAddress(srcIp).toString()),
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
Device(DeviceManager *deviceManager);
|
||||
|
||||
void setVlan(int index, quint16 vlan);
|
||||
quint64 mac();
|
||||
void setMac(quint64 mac);
|
||||
void setIp4(quint32 address, int prefixLength, quint32 gateway);
|
||||
QString config();
|
||||
@ -54,6 +55,9 @@ public:
|
||||
void resolveNeighbor(PacketBuffer *pktBuf);
|
||||
void getNeighbors(OstEmul::DeviceNeighbors *neighbors);
|
||||
|
||||
bool isOrigin(const PacketBuffer *pktBuf);
|
||||
quint64 neighborMac(const PacketBuffer *pktBuf);
|
||||
|
||||
private: // methods
|
||||
void receiveArp(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)
|
||||
{
|
||||
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();
|
||||
int offset = 0;
|
||||
int offset = 12; // start parsing after mac addresses
|
||||
Device dk(this);
|
||||
Device *device;
|
||||
quint64 dstMac = kBcastMac;
|
||||
quint16 ethType;
|
||||
quint16 vlan;
|
||||
int idx = 0;
|
||||
|
||||
// NOTE:
|
||||
// 1. Since resolution hasn't happened yet, dstMac will not be valid;
|
||||
// so we use the Bcast address instead
|
||||
// 2. We assume pkt is ethernet; TODO: extend for other link layer types
|
||||
// pktBuf will not have the correct dstMac populated, so use bcastMac
|
||||
// and search for device by IP
|
||||
|
||||
// FIXME: validate before extracting if the offset is within pktLen
|
||||
|
||||
dk.setMac(dstMac);
|
||||
offset += 6;
|
||||
|
||||
// Skip srcMac - don't care
|
||||
offset += 6;
|
||||
|
||||
qDebug("dstMac %012" PRIx64, dstMac);
|
||||
dk.setMac(kBcastMac);
|
||||
|
||||
_eth_type:
|
||||
// Extract EthType
|
||||
ethType = qFromBigEndian<quint16>(pktData + offset);
|
||||
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
|
||||
|
||||
@ -271,29 +282,13 @@ _eth_type:
|
||||
|
||||
pktBuf->pull(offset);
|
||||
|
||||
if (dstMac == kBcastMac) {
|
||||
QList<Device*> list = bcastList_.values(dk.key());
|
||||
// FIXME: We need to clone the pktBuf before passing to each
|
||||
// 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;
|
||||
foreach(Device *device, bcastList_.values(dk.key())) {
|
||||
if (device->isOrigin(pktBuf))
|
||||
return device;
|
||||
}
|
||||
|
||||
// Is it destined for us?
|
||||
device = deviceList_.value(dk.key());
|
||||
if (!device) {
|
||||
qDebug("%s: dstMac %012llx is not us", __FUNCTION__, dstMac);
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
device->receivePacket(pktBuf);
|
||||
|
||||
_exit:
|
||||
return;
|
||||
qDebug("couldn't find origin device for packet");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DeviceManager::enumerateDevices(
|
||||
|
@ -55,9 +55,12 @@ public:
|
||||
void resolveDeviceNeighbor(PacketBuffer *pktBuf);
|
||||
void getDeviceNeighbors(OstProto::DeviceNeighborList *neighborList);
|
||||
|
||||
quint64 deviceMacAddress(PacketBuffer *pktBuf);
|
||||
quint64 neighborMacAddress(PacketBuffer *pktBuf);
|
||||
private:
|
||||
enum Operation { kAdd, kDelete };
|
||||
|
||||
Device* originDevice(PacketBuffer *pktBuf);
|
||||
void enumerateDevices(
|
||||
const OstProto::DeviceGroup *deviceGroup,
|
||||
Operation oper);
|
||||
|
@ -58,3 +58,8 @@ bool Drone::init()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MyService* Drone::rpcService()
|
||||
{
|
||||
return service;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
Drone(QObject *parent = 0);
|
||||
~Drone();
|
||||
bool init();
|
||||
MyService* rpcService();
|
||||
|
||||
private:
|
||||
RpcServer *rpcServer;
|
||||
|
@ -35,6 +35,7 @@ extern ProtocolManager *OstProtocolManager;
|
||||
extern char *version;
|
||||
extern char *revision;
|
||||
|
||||
Drone *drone;
|
||||
QSettings *appSettings;
|
||||
int myport;
|
||||
|
||||
@ -47,7 +48,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
int exitCode = 0;
|
||||
QCoreApplication app(argc, argv);
|
||||
Drone *drone;
|
||||
|
||||
// TODO: command line options
|
||||
// -v (--version)
|
||||
|
@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#include "myservice.h"
|
||||
|
||||
#include "drone.h"
|
||||
|
||||
#if 0
|
||||
#include <qglobal.h>
|
||||
#include <qendian.h>
|
||||
@ -38,6 +40,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
extern Drone *drone;
|
||||
extern char *version;
|
||||
|
||||
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
|
||||
// expected in a subsequent "modifyStream" request - set the stream id
|
||||
// now itself however!!!
|
||||
stream = new StreamBase;
|
||||
stream = new StreamBase(portId);
|
||||
stream->setId(request->stream_id(i).id());
|
||||
portInfo[portId]->addStream(stream);
|
||||
}
|
||||
@ -360,6 +363,8 @@ void MyService::startTransmit(::google::protobuf::RpcController* /*controller*/,
|
||||
continue; //! \todo (LOW): partial RPC?
|
||||
|
||||
portLock[portId]->lockForWrite();
|
||||
if (portInfo[portId]->isDirty())
|
||||
portInfo[portId]->updatePacketList();
|
||||
portInfo[portId]->startTransmit();
|
||||
portLock[portId]->unlock();
|
||||
}
|
||||
@ -899,3 +904,33 @@ _invalid_port:
|
||||
controller->SetFailed("Invalid Port Id");
|
||||
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,
|
||||
::OstProto::DeviceNeighborList* response,
|
||||
::google::protobuf::Closure* done);
|
||||
|
||||
friend quint64 getDeviceMacAddress(
|
||||
int portId, int streamId, int frameIndex);
|
||||
friend quint64 getNeighborMacAddress(
|
||||
int portId, int streamId, int frameIndex);
|
||||
signals:
|
||||
void notification(int notifType, SharedProtobufMessage notifData);
|
||||
|
||||
|
@ -49,27 +49,27 @@ PacketBuffer::~PacketBuffer()
|
||||
delete[] buffer_;
|
||||
}
|
||||
|
||||
int PacketBuffer::length()
|
||||
int PacketBuffer::length() const
|
||||
{
|
||||
return tail_ - data_;
|
||||
}
|
||||
|
||||
uchar* PacketBuffer::head()
|
||||
uchar* PacketBuffer::head() const
|
||||
{
|
||||
return head_;
|
||||
}
|
||||
|
||||
uchar* PacketBuffer::data()
|
||||
uchar* PacketBuffer::data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
uchar* PacketBuffer::tail()
|
||||
uchar* PacketBuffer::tail() const
|
||||
{
|
||||
return tail_;
|
||||
}
|
||||
|
||||
uchar* PacketBuffer::end()
|
||||
uchar* PacketBuffer::end() const
|
||||
{
|
||||
return end_;
|
||||
}
|
||||
|
@ -29,12 +29,12 @@ public:
|
||||
PacketBuffer(const uchar *buffer, int size);
|
||||
~PacketBuffer();
|
||||
|
||||
int length();
|
||||
int length() const;
|
||||
|
||||
uchar* head();
|
||||
uchar* data();
|
||||
uchar* tail();
|
||||
uchar* end();
|
||||
uchar* head() const;
|
||||
uchar* data() const;
|
||||
uchar* tail() const;
|
||||
uchar* end() const;
|
||||
|
||||
void reserve(int len);
|
||||
uchar* pull(int len);
|
||||
|
@ -14,7 +14,7 @@ from harness import Test, TestSuite, TestPreRequisiteError
|
||||
sys.path.insert(1, '../binding')
|
||||
from core import ost_pb, emul, DroneProxy
|
||||
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.vlan_pb2 import vlan
|
||||
|
||||
@ -263,8 +263,8 @@ try:
|
||||
# setup stream protocols as mac:eth2:ip4:udp:payload
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kMacFieldNumber
|
||||
p.Extensions[mac].dst_mac = dut_dst_mac
|
||||
p.Extensions[mac].src_mac = 0x00aabbccddee
|
||||
p.Extensions[mac].dst_mac_mode = Mac.e_mm_resolve
|
||||
p.Extensions[mac].src_mac_mode = Mac.e_mm_resolve
|
||||
|
||||
p = s.protocol.add()
|
||||
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)
|
||||
suite.test_end(passed)
|
||||
|
||||
sys.exit(1)
|
||||
# FIXME: update the below test cases to resolve Neighbors and streams
|
||||
# to derive src/dst mac from device
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user