Feature (contd.): Device Emulation - user now configures a device group instead of a single device for easier creation of multiple devices; refactored and redistributed functionality between DeviceManager and Device; external functionality wise same as last commit; added initial code for vlans but not tested
This commit is contained in:
parent
ab433dc22b
commit
246bc95c74
@ -21,46 +21,74 @@ import "protocol.proto";
|
||||
|
||||
package OstEmul;
|
||||
|
||||
message MacEmulation {
|
||||
optional uint64 addr = 10;
|
||||
}
|
||||
|
||||
extend OstProto.Device {
|
||||
optional MacEmulation mac = 200;
|
||||
}
|
||||
|
||||
// ======
|
||||
// VLAN
|
||||
// ======
|
||||
message VlanEmulation {
|
||||
enum Mode {
|
||||
kNoRepeat = 0;
|
||||
kRepeat = 1;
|
||||
}
|
||||
message Vlan {
|
||||
optional uint32 tpid = 1 [default = 0x8100];
|
||||
optional uint32 vlan_tag = 2; // includes prio, cfi and vlanid
|
||||
|
||||
// includes prio, cfi and vlanid
|
||||
optional uint32 vlan_tag = 2 [default = 100];
|
||||
|
||||
optional uint32 count = 10 [default = 1];
|
||||
optional uint32 step = 11 [default = 1];
|
||||
optional Mode mode = 12 [default = kRepeat];
|
||||
}
|
||||
// FIXME: rename as just stack?
|
||||
repeated Vlan vlan_stack = 11; // outer to inner
|
||||
|
||||
repeated Vlan stack = 1; // outer to inner
|
||||
}
|
||||
|
||||
extend OstProto.Device {
|
||||
optional VlanEmulation vlan = 201;
|
||||
extend OstProto.DeviceGroup {
|
||||
optional VlanEmulation vlan = 200;
|
||||
}
|
||||
|
||||
// ========
|
||||
// Device
|
||||
// ========
|
||||
message MacEmulation {
|
||||
optional uint64 address = 1; // FIXME: default value
|
||||
|
||||
optional uint64 step = 10 [default = 1];
|
||||
}
|
||||
|
||||
message Ip4Emulation {
|
||||
optional uint32 addr = 2;
|
||||
optional uint32 prefix_length = 3;
|
||||
optional uint32 gateway = 4; // FIXME: rename to default_gateway?
|
||||
}
|
||||
optional uint32 address = 1;
|
||||
optional uint32 prefix_length = 2;
|
||||
optional uint32 default_gateway = 3;
|
||||
|
||||
extend OstProto.Device {
|
||||
optional Ip4Emulation ip4 = 300;
|
||||
optional uint64 step = 10 [default = 1];
|
||||
// FIXME: step for gateway?
|
||||
}
|
||||
|
||||
message Ip6Emulation {
|
||||
optional uint64 addr_hi = 31;
|
||||
optional uint64 addr_lo = 32;
|
||||
optional uint32 prefix_length = 33;
|
||||
optional uint64 gateway_hi = 34;
|
||||
optional uint64 gateway_lo = 35;
|
||||
optional uint64 address_hi = 1;
|
||||
optional uint64 address_lo = 2;
|
||||
optional uint32 prefix_length = 3;
|
||||
optional uint64 default_gateway_hi = 4;
|
||||
optional uint64 default_gateway_lo = 5;
|
||||
|
||||
optional uint64 step_hi = 10 [default = 0];
|
||||
optional uint64 step_lo = 11 [default = 1];
|
||||
}
|
||||
|
||||
extend OstProto.Device {
|
||||
optional Ip6Emulation ip6 = 301;
|
||||
message Device {
|
||||
enum Mode {
|
||||
kNoRepeat = 0;
|
||||
kRepeat = 1;
|
||||
}
|
||||
optional MacEmulation mac = 1;
|
||||
optional Ip4Emulation ip4 = 2;
|
||||
optional Ip6Emulation ip6 = 3;
|
||||
|
||||
optional uint32 count = 10 [default = 1];
|
||||
optional Mode mode = 11 [default = kRepeat]; // FIXME: per proto mode?
|
||||
}
|
||||
|
||||
extend OstProto.DeviceGroup {
|
||||
optional Device device = 201;
|
||||
}
|
||||
|
@ -278,32 +278,33 @@ message Notification {
|
||||
* Protocol Emulation
|
||||
* FIXME: review/fix tag numbers
|
||||
* FIXME: move xxxEmulation to their own .proto files?
|
||||
* FIXME: What will be the contents of a default device created by addDevice()?
|
||||
* FIXME: What will be the contents of a default device created by addDeviceGroup()?
|
||||
* FIXME: decide default values for device and protoEmulations
|
||||
* FIXME: rename 'DeviceGroup'?
|
||||
*/
|
||||
message DeviceId {
|
||||
message DeviceGroupId {
|
||||
required uint32 id = 1;
|
||||
}
|
||||
|
||||
message DeviceCore {
|
||||
message DeviceGroupCore {
|
||||
optional string name = 1;
|
||||
}
|
||||
|
||||
message DeviceIdList {
|
||||
message DeviceGroupIdList {
|
||||
required PortId port_id = 1;
|
||||
repeated DeviceId device_id = 2;
|
||||
repeated DeviceGroupId device_group_id = 2;
|
||||
}
|
||||
|
||||
message Device {
|
||||
required DeviceId device_id = 1;
|
||||
optional DeviceCore core = 2;
|
||||
message DeviceGroup {
|
||||
required DeviceGroupId device_group_id = 1;
|
||||
optional DeviceGroupCore core = 2;
|
||||
|
||||
extensions 200 to 500; // For use by Protocol Emulations
|
||||
}
|
||||
|
||||
message DeviceConfigList {
|
||||
message DeviceGroupConfigList {
|
||||
required PortId port_id = 1;
|
||||
repeated Device device = 2;
|
||||
repeated DeviceGroup device_group = 2;
|
||||
}
|
||||
|
||||
service OstService {
|
||||
@ -329,11 +330,11 @@ service OstService {
|
||||
|
||||
rpc checkVersion(VersionInfo) returns (VersionCompatibility);
|
||||
|
||||
// Device Protocol Emulation
|
||||
rpc getDeviceIdList(PortId) returns (DeviceIdList);
|
||||
rpc getDeviceConfig(DeviceIdList) returns (DeviceConfigList);
|
||||
rpc addDevice(DeviceIdList) returns (Ack);
|
||||
rpc deleteDevice(DeviceIdList) returns (Ack);
|
||||
rpc modifyDevice(DeviceConfigList) returns (Ack);
|
||||
// Device/Protocol Emulation
|
||||
rpc getDeviceGroupIdList(PortId) returns (DeviceGroupIdList);
|
||||
rpc getDeviceGroupConfig(DeviceGroupIdList) returns (DeviceGroupConfigList);
|
||||
rpc addDeviceGroup(DeviceGroupIdList) returns (Ack);
|
||||
rpc deleteDeviceGroup(DeviceGroupIdList) returns (Ack);
|
||||
rpc modifyDeviceGroup(DeviceGroupConfigList) returns (Ack);
|
||||
}
|
||||
|
||||
|
@ -23,78 +23,99 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include "devicemanager.h"
|
||||
#include "packetbuffer.h"
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <qendian.h>
|
||||
|
||||
QHash<quint64, Device*> Device::macHash_;
|
||||
QHash<quint32, Device*> Device::ip4Hash_;
|
||||
const int kBaseHex = 16;
|
||||
const int kMaxVlan = 4;
|
||||
|
||||
Device::Device(quint32 id, DeviceManager *deviceManager)
|
||||
/*
|
||||
* NOTE:
|
||||
* 1. Device Key is (VLANS + MAC) - is assumed to be unique for a device
|
||||
* 2. Device clients/users (viz. DeviceManager) should take care when
|
||||
* setting params that change the key, if the key is used elsewhere
|
||||
* (e.g. in a hash)
|
||||
*/
|
||||
|
||||
Device::Device(DeviceManager *deviceManager)
|
||||
{
|
||||
deviceManager_ = deviceManager;
|
||||
data_.mutable_device_id()->set_id(id);
|
||||
// FIXME: choose a better default mac address
|
||||
data_.MutableExtension(OstEmul::mac)->set_addr(0x001122330000ULL + id);
|
||||
|
||||
Device::macHash_.insert(myMac(), this);
|
||||
for (int i = 0; i < kMaxVlan; i++)
|
||||
vlan_[i] = 0;
|
||||
numVlanTags_ = 0;
|
||||
mac_ = 0;
|
||||
ip4_ = 0;
|
||||
ip4PrefixLength_ = 0;
|
||||
|
||||
clearKey();
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
void Device::setVlan(int index, quint16 vlan)
|
||||
{
|
||||
macHash_.remove(myMac());
|
||||
ip4Hash_.remove(myIp4());
|
||||
}
|
||||
int ofs;
|
||||
|
||||
quint32 Device::id()
|
||||
{
|
||||
return data_.device_id().id();
|
||||
}
|
||||
|
||||
void Device::protoDataCopyFrom(const OstProto::Device &device)
|
||||
{
|
||||
quint64 oldMac, newMac;
|
||||
quint32 oldIp4, newIp4;
|
||||
|
||||
// Save old mac and ip before updating the device data
|
||||
oldMac = myMac();
|
||||
oldIp4 = myIp4();
|
||||
|
||||
data_.CopyFrom(device);
|
||||
|
||||
// Get new mac and ip for comparison
|
||||
newMac = myMac();
|
||||
newIp4 = myIp4();
|
||||
|
||||
// Update MacHash if mac has changed
|
||||
if (newMac != oldMac) {
|
||||
macHash_.remove(oldMac);
|
||||
macHash_.insert(newMac, this);
|
||||
if ((index < 0) || (index >= kMaxVlan)) {
|
||||
qWarning("%s: vlan index %d out of range (0 - %d)", __FUNCTION__,
|
||||
index, kMaxVlan - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update Ip4Hash if ip4 has changed
|
||||
if (newIp4 != oldIp4) {
|
||||
ip4Hash_.remove(oldIp4);
|
||||
ip4Hash_.insert(newIp4, this);
|
||||
}
|
||||
vlan_[index] = vlan;
|
||||
|
||||
ofs = index * sizeof(quint16);
|
||||
key_[ofs] = vlan >> 8;
|
||||
key_[ofs+1] = vlan & 0xff;
|
||||
|
||||
if (index >= numVlanTags_)
|
||||
numVlanTags_ = index + 1;
|
||||
}
|
||||
|
||||
void Device::protoDataCopyInto(OstProto::Device &device) const
|
||||
void Device::setMac(quint64 mac)
|
||||
{
|
||||
device.CopyFrom(data_);
|
||||
int ofs = kMaxVlan * sizeof(quint16);
|
||||
|
||||
mac_ = mac;
|
||||
memcpy(key_.data() + ofs, (char*)&mac, sizeof(mac));
|
||||
}
|
||||
|
||||
void Device::setIp4(quint32 address, int prefixLength)
|
||||
{
|
||||
ip4_ = address;
|
||||
ip4PrefixLength_ = prefixLength;
|
||||
}
|
||||
|
||||
QString Device::config()
|
||||
{
|
||||
return QString("<vlans=%1/%2/%3/%4 mac=%5 ip4=%6/%7>")
|
||||
.arg(vlan_[0]).arg(vlan_[1]).arg(vlan_[2]).arg(vlan_[3])
|
||||
.arg(mac_, 12, kBaseHex, QChar('0'))
|
||||
.arg(QHostAddress(ip4_).toString())
|
||||
.arg(ip4PrefixLength_);
|
||||
}
|
||||
|
||||
DeviceKey Device::key()
|
||||
{
|
||||
return key_;
|
||||
}
|
||||
|
||||
void Device::clearKey()
|
||||
{
|
||||
key_.fill(0, kMaxVlan * sizeof(quint16) + sizeof(quint64));
|
||||
}
|
||||
|
||||
int Device::encapSize()
|
||||
{
|
||||
int size = 14; // ethernet header size
|
||||
|
||||
if (data_.HasExtension(OstEmul::vlan))
|
||||
size += 4 * data_.GetExtension(OstEmul::vlan).vlan_stack_size();
|
||||
// ethernet header + vlans
|
||||
int size = 14 + 4*numVlanTags_;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void Device::encap(PacketBuffer *pktBuf, quint64 dstMac, quint16 type)
|
||||
{
|
||||
quint64 srcMac = myMac();
|
||||
int ofs;
|
||||
quint64 srcMac = mac_;
|
||||
uchar *p = pktBuf->push(encapSize());
|
||||
|
||||
if (!p) {
|
||||
@ -107,90 +128,52 @@ void Device::encap(PacketBuffer *pktBuf, quint64 dstMac, quint16 type)
|
||||
*(quint16*)(p + 4) = qToBigEndian(quint16(dstMac & 0xffff));
|
||||
*(quint32*)(p + 6) = qToBigEndian(quint32(srcMac >> 16));
|
||||
*(quint16*)(p + 10) = qToBigEndian(quint16(srcMac & 0xffff));
|
||||
// TODO: Vlan Encap
|
||||
*(quint16*)(p + 12) = qToBigEndian(type);
|
||||
ofs = 12;
|
||||
for (int i = 0; i < numVlanTags_; i++) {
|
||||
*(quint16*)(p + ofs) = qToBigEndian(quint32((0x8100 << 16)|vlan_[i]));
|
||||
ofs += 4;
|
||||
}
|
||||
*(quint16*)(p + ofs) = qToBigEndian(type);
|
||||
ofs += 2;
|
||||
|
||||
Q_ASSERT(ofs == encapSize());
|
||||
|
||||
_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Private Methods
|
||||
//
|
||||
quint64 Device::myMac()
|
||||
{
|
||||
if (data_.HasExtension(OstEmul::mac))
|
||||
return data_.GetExtension(OstEmul::mac).addr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
quint32 Device::myIp4()
|
||||
{
|
||||
if (data_.HasExtension(OstEmul::ip4))
|
||||
return data_.GetExtension(OstEmul::ip4).addr();
|
||||
|
||||
return 0; // FIXME: how to indicate that we don't have a IP?
|
||||
}
|
||||
|
||||
void Device::transmitPacket(PacketBuffer *pktBuf)
|
||||
{
|
||||
deviceManager_->transmitPacket(pktBuf);
|
||||
}
|
||||
|
||||
// We expect pktBuf to point to EthType on entry
|
||||
void Device::receivePacket(PacketBuffer *pktBuf)
|
||||
{
|
||||
uchar *pktData = pktBuf->data();
|
||||
int offset = 0;
|
||||
Device *device;
|
||||
const quint64 bcastMac = 0xffffffffffffULL;
|
||||
quint64 dstMac;
|
||||
quint16 ethType;
|
||||
quint16 ethType = qFromBigEndian<quint16>(pktBuf->data());
|
||||
pktBuf->pull(2);
|
||||
|
||||
// We assume pkt is ethernet
|
||||
// TODO: extend for other link layer types
|
||||
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
|
||||
|
||||
// Extract dstMac
|
||||
dstMac = qFromBigEndian<quint32>(pktData + offset);
|
||||
offset += 4;
|
||||
dstMac = (dstMac << 16) | qFromBigEndian<quint16>(pktData + offset);
|
||||
offset += 2;
|
||||
|
||||
// Skip srcMac - don't care
|
||||
offset += 6;
|
||||
qDebug("dstMac %llx", dstMac);
|
||||
|
||||
// Is it destined for us?
|
||||
device = macHash_.value(dstMac);
|
||||
if (!device && (dstMac != bcastMac)) {
|
||||
qDebug("%s: dstMac %llx is not us", __FUNCTION__, dstMac);
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
ethType = qFromBigEndian<quint16>(pktData + offset);
|
||||
offset += 2;
|
||||
qDebug("%s: ethType 0x%x", __FUNCTION__, ethType);
|
||||
|
||||
switch(ethType)
|
||||
{
|
||||
case 0x0806: // ARP
|
||||
pktBuf->pull(offset);
|
||||
receiveArp(device, pktBuf);
|
||||
receiveArp(pktBuf);
|
||||
break;
|
||||
|
||||
case 0x8100: // VLAN
|
||||
case 0x0800: // IPv4
|
||||
case 0x86dd: // IPv6
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Device::receiveArp(Device *device, PacketBuffer *pktBuf)
|
||||
//
|
||||
// Private Methods
|
||||
//
|
||||
void Device::receiveArp(PacketBuffer *pktBuf)
|
||||
{
|
||||
PacketBuffer *rspPkt;
|
||||
uchar *pktData = pktBuf->data();
|
||||
int offset = 0;
|
||||
quint16 hwType, protoType;
|
||||
@ -199,6 +182,15 @@ void Device::receiveArp(Device *device, PacketBuffer *pktBuf)
|
||||
quint64 srcMac, tgtMac;
|
||||
quint32 srcIp, tgtIp;
|
||||
|
||||
// Extract tgtIp first to check quickly if this packet is for us or not
|
||||
tgtIp = qFromBigEndian<quint32>(pktData + 24);
|
||||
if (tgtIp != ip4_) {
|
||||
qDebug("tgtIp %s is not me %s",
|
||||
qPrintable(QHostAddress(tgtIp).toString()),
|
||||
qPrintable(QHostAddress(ip4_).toString()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract annd verify ARP packet contents
|
||||
hwType = qFromBigEndian<quint16>(pktData + offset);
|
||||
offset += 2;
|
||||
@ -236,43 +228,33 @@ void Device::receiveArp(Device *device, PacketBuffer *pktBuf)
|
||||
tgtMac = (tgtMac << 16) | qFromBigEndian<quint16>(pktData + offset);
|
||||
offset += 2;
|
||||
|
||||
tgtIp = qFromBigEndian<quint32>(pktData + offset);
|
||||
offset += 4;
|
||||
|
||||
switch (opCode)
|
||||
{
|
||||
case 1: // ARP Request
|
||||
if (!device)
|
||||
device = ip4Hash_.value(tgtIp);
|
||||
if (device->myIp4() == tgtIp) {
|
||||
PacketBuffer *pktBuf = new PacketBuffer;
|
||||
uchar *p;
|
||||
|
||||
pktBuf->reserve(device->encapSize());
|
||||
p = pktBuf->put(28); // FIXME: hardcoding
|
||||
if (p) {
|
||||
// HTYP, PTYP
|
||||
*(quint32*)(p ) = qToBigEndian(quint32(0x00010800));
|
||||
// HLEN, PLEN, OPER
|
||||
*(quint32*)(p+ 4) = qToBigEndian(quint32(0x06040002));
|
||||
// Source H/W Addr, Proto Addr
|
||||
*(quint32*)(p+ 8) = qToBigEndian(
|
||||
quint32(device->myMac() >> 16));
|
||||
*(quint16*)(p+12) = qToBigEndian(
|
||||
quint16(device->myMac() & 0xffff));
|
||||
*(quint32*)(p+14) = qToBigEndian(tgtIp);
|
||||
// Target H/W Addr, Proto Addr
|
||||
*(quint32*)(p+18) = qToBigEndian(quint32(srcMac >> 16));
|
||||
*(quint16*)(p+22) = qToBigEndian(quint16(srcMac & 0xffff));
|
||||
*(quint32*)(p+24) = qToBigEndian(srcIp);
|
||||
}
|
||||
|
||||
device->encap(pktBuf, srcMac, 0x0806);
|
||||
device->transmitPacket(pktBuf);
|
||||
|
||||
qDebug("Sent ARP Reply for srcIp/tgtIp=0x%x/0x%x",
|
||||
srcIp, tgtIp);
|
||||
case 1: // ARP Request
|
||||
rspPkt = new PacketBuffer;
|
||||
rspPkt->reserve(encapSize());
|
||||
pktData = rspPkt->put(28);
|
||||
if (pktData) {
|
||||
// HTYP, PTYP
|
||||
*(quint32*)(pktData ) = qToBigEndian(quint32(0x00010800));
|
||||
// HLEN, PLEN, OPER
|
||||
*(quint32*)(pktData+ 4) = qToBigEndian(quint32(0x06040002));
|
||||
// Source H/W Addr, Proto Addr
|
||||
*(quint32*)(pktData+ 8) = qToBigEndian(quint32(mac_ >> 16));
|
||||
*(quint16*)(pktData+12) = qToBigEndian(quint16(mac_ & 0xffff));
|
||||
*(quint32*)(pktData+14) = qToBigEndian(ip4_);
|
||||
// Target H/W Addr, Proto Addr
|
||||
*(quint32*)(pktData+18) = qToBigEndian(quint32(srcMac >> 16));
|
||||
*(quint16*)(pktData+22) = qToBigEndian(quint16(srcMac & 0xffff));
|
||||
*(quint32*)(pktData+24) = qToBigEndian(srcIp);
|
||||
}
|
||||
|
||||
encap(rspPkt, srcMac, 0x0806);
|
||||
transmitPacket(rspPkt);
|
||||
|
||||
qDebug("Sent ARP Reply for srcIp/tgtIp=%s/%s",
|
||||
qPrintable(QHostAddress(srcIp).toString()),
|
||||
qPrintable(QHostAddress(tgtIp).toString()));
|
||||
break;
|
||||
case 2: // ARP Response
|
||||
default:
|
||||
|
@ -22,45 +22,45 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#include "../common/protocol.pb.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QByteArray>
|
||||
|
||||
class DeviceManager;
|
||||
class PacketBuffer;
|
||||
|
||||
typedef QByteArray DeviceKey;
|
||||
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
Device(quint32 id, DeviceManager *deviceManager);
|
||||
~Device();
|
||||
Device(DeviceManager *deviceManager);
|
||||
|
||||
quint32 id();
|
||||
void setVlan(int index, quint16 vlan);
|
||||
void setMac(quint64 mac);
|
||||
void setIp4(quint32 address, int prefixLength);
|
||||
QString config();
|
||||
|
||||
void protoDataCopyFrom(const OstProto::Device &device);
|
||||
void protoDataCopyInto(OstProto::Device &device) const;
|
||||
DeviceKey key();
|
||||
void clearKey();
|
||||
|
||||
int encapSize();
|
||||
void encap(PacketBuffer *pktBuf, quint64 dstMac, quint16 type);
|
||||
|
||||
// receivePacket() is a class method 'coz we don't have the target
|
||||
// device yet; transmitPacket() is always from a particular device
|
||||
void receivePacket(PacketBuffer *pktBuf);
|
||||
void transmitPacket(PacketBuffer *pktBuf);
|
||||
static void receivePacket(PacketBuffer *pktBuf);
|
||||
|
||||
private: // methods
|
||||
// receiveArp() is a class method 'coz ARP request is broadcast, so
|
||||
// we can't identify the target device till we parse the ARP header
|
||||
static void receiveArp(Device *device, PacketBuffer *pktBuf);
|
||||
|
||||
quint64 myMac();
|
||||
quint32 myIp4();
|
||||
void receiveArp(PacketBuffer *pktBuf);
|
||||
|
||||
private: // data
|
||||
// Class data
|
||||
static QHash<quint64, Device*> macHash_;
|
||||
static QHash<quint32, Device*> ip4Hash_;
|
||||
|
||||
DeviceManager *deviceManager_;
|
||||
OstProto::Device data_;
|
||||
|
||||
int numVlanTags_;
|
||||
quint16 vlan_[4]; // FIXME: vlan tpid
|
||||
quint64 mac_;
|
||||
quint32 ip4_;
|
||||
int ip4PrefixLength_;
|
||||
|
||||
DeviceKey key_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -23,9 +23,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include "device.h"
|
||||
#include "packetbuffer.h"
|
||||
|
||||
#include "../common/emulproto.pb.h"
|
||||
|
||||
#include <qendian.h>
|
||||
|
||||
// FIXME: add lock to protect deviceList_ operations?
|
||||
const quint64 kBcastMac = 0xffffffffffffULL;
|
||||
|
||||
// FIXME: add lock to protect deviceGroupList_ operations?
|
||||
|
||||
DeviceManager::DeviceManager(AbstractPort *parent)
|
||||
{
|
||||
@ -36,6 +40,90 @@ DeviceManager::~DeviceManager()
|
||||
{
|
||||
foreach(Device *dev, deviceList_)
|
||||
delete dev;
|
||||
|
||||
foreach(OstProto::DeviceGroup *devGrp, deviceGroupList_)
|
||||
delete devGrp;
|
||||
}
|
||||
|
||||
int DeviceManager::deviceGroupCount()
|
||||
{
|
||||
return deviceGroupList_.size();
|
||||
}
|
||||
|
||||
const OstProto::DeviceGroup* DeviceManager::deviceGroupAtIndex(int index)
|
||||
{
|
||||
if ((index < 0) || (index >= deviceGroupCount())) {
|
||||
qWarning("%s: index %d out of range (0 - %d)", __FUNCTION__,
|
||||
index, deviceGroupCount() - 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Sort List by 'id', get the id at 'index' and then corresponding devGrp
|
||||
return deviceGroupList_.value(deviceGroupList_.uniqueKeys().value(index));
|
||||
}
|
||||
|
||||
const OstProto::DeviceGroup* DeviceManager::deviceGroup(uint deviceGroupId)
|
||||
{
|
||||
return deviceGroupList_.value(deviceGroupId);
|
||||
}
|
||||
|
||||
bool DeviceManager::addDeviceGroup(uint deviceGroupId)
|
||||
{
|
||||
OstProto::DeviceGroup *deviceGroup;
|
||||
|
||||
if (deviceGroupList_.contains(deviceGroupId)) {
|
||||
qWarning("%s: deviceGroup id %u already exists", __FUNCTION__,
|
||||
deviceGroupId);
|
||||
return false;
|
||||
}
|
||||
|
||||
deviceGroup = new OstProto::DeviceGroup;
|
||||
deviceGroup->mutable_device_group_id()->set_id(deviceGroupId);
|
||||
deviceGroupList_.insert(deviceGroupId, deviceGroup);
|
||||
|
||||
enumerateDevices(deviceGroup, kAdd);
|
||||
|
||||
// Start emulation when first device is added
|
||||
if ((deviceCount() == 1) && port_)
|
||||
port_->startDeviceEmulation();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceManager::deleteDeviceGroup(uint deviceGroupId)
|
||||
{
|
||||
OstProto::DeviceGroup *deviceGroup;
|
||||
if (!deviceGroupList_.contains(deviceGroupId)) {
|
||||
qWarning("%s: deviceGroup id %u does not exist", __FUNCTION__,
|
||||
deviceGroupId);
|
||||
return false;
|
||||
}
|
||||
|
||||
deviceGroup = deviceGroupList_.take(deviceGroupId);
|
||||
enumerateDevices(deviceGroup, kDelete);
|
||||
delete deviceGroup;
|
||||
|
||||
// Stop emulation if no devices remain
|
||||
if ((deviceCount() == 0) && port_)
|
||||
port_->stopDeviceEmulation();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceManager::modifyDeviceGroup(const OstProto::DeviceGroup *deviceGroup)
|
||||
{
|
||||
quint32 id = deviceGroup->device_group_id().id();
|
||||
OstProto::DeviceGroup *myDeviceGroup = deviceGroupList_.value(id);
|
||||
if (!myDeviceGroup) {
|
||||
qWarning("%s: deviceGroup id %u does not exist", __FUNCTION__, id);
|
||||
return false;
|
||||
}
|
||||
|
||||
enumerateDevices(myDeviceGroup, kDelete);
|
||||
myDeviceGroup->CopyFrom(*deviceGroup);
|
||||
enumerateDevices(myDeviceGroup, kAdd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int DeviceManager::deviceCount()
|
||||
@ -43,75 +131,155 @@ int DeviceManager::deviceCount()
|
||||
return deviceList_.size();
|
||||
}
|
||||
|
||||
Device* DeviceManager::deviceAtIndex(int index)
|
||||
{
|
||||
if ((index < 0) || (index >= deviceCount())) {
|
||||
qWarning("%s: index %d out of range (max %d)", __FUNCTION__,
|
||||
index, deviceCount());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return deviceList_.value(deviceList_.uniqueKeys().value(index));
|
||||
}
|
||||
|
||||
Device* DeviceManager::device(uint deviceId)
|
||||
{
|
||||
return deviceList_.value(deviceId);
|
||||
}
|
||||
|
||||
bool DeviceManager::addDevice(uint deviceId)
|
||||
{
|
||||
Device *device;
|
||||
|
||||
if (deviceList_.contains(deviceId)) {
|
||||
qWarning("%s: device id %u already exists", __FUNCTION__, deviceId);
|
||||
return false;
|
||||
}
|
||||
|
||||
device = new Device(deviceId, this);
|
||||
deviceList_.insert(deviceId, device);
|
||||
|
||||
if ((deviceCount() == 1) && port_)
|
||||
port_->startDeviceEmulation();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceManager::deleteDevice(uint deviceId)
|
||||
{
|
||||
if (!deviceList_.contains(deviceId)) {
|
||||
qWarning("%s: device id %u does not exist", __FUNCTION__, deviceId);
|
||||
return false;
|
||||
}
|
||||
|
||||
delete deviceList_.take(deviceId);
|
||||
|
||||
if ((deviceCount() == 0) && port_)
|
||||
port_->stopDeviceEmulation();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceManager::modifyDevice(const OstProto::Device *device)
|
||||
{
|
||||
quint32 id = device->device_id().id();
|
||||
Device *myDevice = deviceList_.value(id);
|
||||
if (!myDevice) {
|
||||
qWarning("%s: device id %u does not exist", __FUNCTION__, id);
|
||||
return false;
|
||||
}
|
||||
|
||||
myDevice->protoDataCopyFrom(*device);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeviceManager::receivePacket(PacketBuffer *pktBuf)
|
||||
{
|
||||
Device::receivePacket(pktBuf);
|
||||
uchar *pktData = pktBuf->data();
|
||||
int offset = 0;
|
||||
Device dk(this);
|
||||
Device *device;
|
||||
quint64 dstMac;
|
||||
quint16 ethType;
|
||||
quint16 vlan;
|
||||
int idx = 0;
|
||||
|
||||
// We assume pkt is ethernet
|
||||
// TODO: extend for other link layer types
|
||||
|
||||
// FIXME: validate before extracting if the offset is within pktLen
|
||||
|
||||
// Extract dstMac
|
||||
dstMac = qFromBigEndian<quint32>(pktData + offset);
|
||||
offset += 4;
|
||||
dstMac = (dstMac << 16) | qFromBigEndian<quint16>(pktData + offset);
|
||||
dk.setMac(dstMac);
|
||||
offset += 2;
|
||||
|
||||
// Skip srcMac - don't care
|
||||
offset += 6;
|
||||
|
||||
qDebug("dstMac %llx", dstMac);
|
||||
|
||||
_eth_type:
|
||||
// Extract EthType
|
||||
ethType = qFromBigEndian<quint16>(pktData + offset);
|
||||
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
|
||||
|
||||
if (ethType == 0x8100) {
|
||||
offset += 2;
|
||||
vlan = qFromBigEndian<quint16>(pktData + offset);
|
||||
dk.setVlan(idx++, vlan);
|
||||
offset += 2;
|
||||
qDebug("%s: idx: %d vlan 0x%x", __FUNCTION__, idx, vlan);
|
||||
goto _eth_type;
|
||||
}
|
||||
|
||||
pktBuf->pull(offset);
|
||||
|
||||
if (dstMac == kBcastMac) {
|
||||
QList<Device*> list = bcastList_.values(dk.key());
|
||||
foreach(Device *device, list)
|
||||
device->receivePacket(pktBuf);
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
void DeviceManager::transmitPacket(PacketBuffer *pktBuf)
|
||||
{
|
||||
port_->sendEmulationPacket(pktBuf);
|
||||
}
|
||||
|
||||
void DeviceManager::enumerateDevices(
|
||||
const OstProto::DeviceGroup *deviceGroup,
|
||||
Operation oper)
|
||||
{
|
||||
Device dk(this);
|
||||
OstEmul::VlanEmulation pbVlan = deviceGroup->GetExtension(OstEmul::vlan);
|
||||
OstEmul::Device pbDevice = deviceGroup->GetExtension(OstEmul::device);
|
||||
int numTags = pbVlan.stack_size();
|
||||
int vlanCount = 1;
|
||||
|
||||
for (int i = 0; i < numTags; i++)
|
||||
vlanCount *= pbVlan.stack(i).count();
|
||||
|
||||
// If we have no vlans, we still have the non-vlan-segmented LAN
|
||||
if (vlanCount == 0)
|
||||
vlanCount = 1;
|
||||
|
||||
for (int i = 0; i < vlanCount; i++) {
|
||||
for (int j = 0; j < numTags; j++) {
|
||||
OstEmul::VlanEmulation::Vlan vlan = pbVlan.stack(j);
|
||||
quint16 vlanAdd = i*vlan.step();
|
||||
|
||||
switch (vlan.mode()) {
|
||||
case OstEmul::VlanEmulation::kNoRepeat:
|
||||
/* Do nothing */
|
||||
break;
|
||||
case OstEmul::VlanEmulation::kRepeat:
|
||||
default:
|
||||
vlanAdd %= vlan.count();
|
||||
break;
|
||||
}
|
||||
|
||||
dk.setVlan(j, vlan.vlan_tag() + vlanAdd);
|
||||
}
|
||||
|
||||
for (uint k = 0; k < pbDevice.count(); k++) {
|
||||
Device *device;
|
||||
quint64 macAdd = i*k*pbDevice.mac().step();
|
||||
quint32 ip4Add = i*k*pbDevice.ip4().step();
|
||||
|
||||
switch (pbDevice.mode()) {
|
||||
case OstEmul::Device::kNoRepeat:
|
||||
/* Do Nothing*/
|
||||
break;
|
||||
case OstEmul::Device::kRepeat:
|
||||
default:
|
||||
macAdd %= pbDevice.count();
|
||||
ip4Add %= pbDevice.count();
|
||||
break;
|
||||
}
|
||||
|
||||
dk.setMac(pbDevice.mac().address() + macAdd);
|
||||
dk.setIp4(pbDevice.ip4().address() + ip4Add,
|
||||
pbDevice.ip4().prefix_length());
|
||||
|
||||
// TODO: fill in other pbDevice data
|
||||
|
||||
switch (oper) {
|
||||
case kAdd:
|
||||
device = new Device(this);
|
||||
*device = dk;
|
||||
deviceList_.insert(dk.key(), device);
|
||||
|
||||
dk.setMac(kBcastMac);
|
||||
bcastList_.insert(dk.key(), device);
|
||||
qDebug("enumerate (add): %s", qPrintable(device->config()));
|
||||
break;
|
||||
|
||||
case kDelete:
|
||||
device = deviceList_.take(dk.key());
|
||||
qDebug("enumerate (del): %s", qPrintable(device->config()));
|
||||
delete device;
|
||||
|
||||
dk.setMac(kBcastMac);
|
||||
bcastList_.take(dk.key()); // device already freed above
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(0); // Unreachable
|
||||
}
|
||||
} // foreach device
|
||||
} // foreach vlan
|
||||
}
|
||||
|
@ -20,14 +20,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#ifndef _DEVICE_MANAGER_H
|
||||
#define _DEVICE_MANAGER_H
|
||||
|
||||
#include "../common/protocol.pb.h"
|
||||
#include "device.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QMultiHash>
|
||||
#include <QtGlobal>
|
||||
|
||||
class AbstractPort;
|
||||
class Device;
|
||||
class PacketBuffer;
|
||||
namespace OstProto {
|
||||
class DeviceGroup;
|
||||
};
|
||||
|
||||
class DeviceManager
|
||||
{
|
||||
@ -35,19 +38,30 @@ public:
|
||||
DeviceManager(AbstractPort *parent = 0);
|
||||
~DeviceManager();
|
||||
|
||||
int deviceCount();
|
||||
Device* deviceAtIndex(int index);
|
||||
Device* device(uint deviceId);
|
||||
int deviceGroupCount();
|
||||
const OstProto::DeviceGroup* deviceGroupAtIndex(int index);
|
||||
const OstProto::DeviceGroup* deviceGroup(uint deviceGroupId);
|
||||
|
||||
bool addDevice(uint deviceId);
|
||||
bool deleteDevice(uint deviceId);
|
||||
bool modifyDevice(const OstProto::Device *device);
|
||||
bool addDeviceGroup(uint deviceGroupId);
|
||||
bool deleteDeviceGroup(uint deviceGroupId);
|
||||
bool modifyDeviceGroup(const OstProto::DeviceGroup *deviceGroup);
|
||||
|
||||
int deviceCount();
|
||||
|
||||
void receivePacket(PacketBuffer *pktBuf);
|
||||
void transmitPacket(PacketBuffer *pktBuf);
|
||||
|
||||
private:
|
||||
enum Operation { kAdd, kDelete };
|
||||
|
||||
void enumerateDevices(
|
||||
const OstProto::DeviceGroup *deviceGroup,
|
||||
Operation oper);
|
||||
|
||||
AbstractPort *port_;
|
||||
QHash<uint, Device*> deviceList_;
|
||||
QHash<uint, OstProto::DeviceGroup*> deviceGroupList_;
|
||||
QHash<DeviceKey, Device*> deviceList_;
|
||||
QMultiHash<DeviceKey, Device*> bcastList_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -33,8 +33,8 @@ LIBS += -lprotobuf
|
||||
HEADERS += drone.h \
|
||||
myservice.h
|
||||
SOURCES += \
|
||||
device.cpp \
|
||||
devicemanager.cpp \
|
||||
device.cpp \
|
||||
drone_main.cpp \
|
||||
drone.cpp \
|
||||
portmanager.cpp \
|
||||
|
@ -602,9 +602,10 @@ _invalid_version:
|
||||
* streams/ports and devices independent?
|
||||
* ===================================================================
|
||||
*/
|
||||
void MyService::getDeviceIdList(::google::protobuf::RpcController* controller,
|
||||
void MyService::getDeviceGroupIdList(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::PortId* request,
|
||||
::OstProto::DeviceIdList* response,
|
||||
::OstProto::DeviceGroupIdList* response,
|
||||
::google::protobuf::Closure* done)
|
||||
{
|
||||
DeviceManager *devMgr;
|
||||
@ -620,12 +621,12 @@ void MyService::getDeviceIdList(::google::protobuf::RpcController* controller,
|
||||
|
||||
response->mutable_port_id()->set_id(portId);
|
||||
portLock[portId]->lockForRead();
|
||||
for (int i = 0; i < devMgr->deviceCount(); i++)
|
||||
for (int i = 0; i < devMgr->deviceGroupCount(); i++)
|
||||
{
|
||||
OstProto::DeviceId *d;
|
||||
OstProto::DeviceGroupId *dgid;
|
||||
|
||||
d = response->add_device_id();
|
||||
d->set_id(devMgr->deviceAtIndex(i)->id());
|
||||
dgid = response->add_device_group_id();
|
||||
dgid->CopyFrom(devMgr->deviceGroupAtIndex(i)->device_group_id());
|
||||
}
|
||||
portLock[portId]->unlock();
|
||||
|
||||
@ -637,9 +638,10 @@ _invalid_port:
|
||||
done->Run();
|
||||
}
|
||||
|
||||
void MyService::getDeviceConfig(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceIdList* request,
|
||||
::OstProto::DeviceConfigList* response,
|
||||
void MyService::getDeviceGroupConfig(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceGroupIdList* request,
|
||||
::OstProto::DeviceGroupConfigList* response,
|
||||
::google::protobuf::Closure* done)
|
||||
{
|
||||
DeviceManager *devMgr;
|
||||
@ -655,17 +657,15 @@ void MyService::getDeviceConfig(::google::protobuf::RpcController* controller,
|
||||
|
||||
response->mutable_port_id()->set_id(portId);
|
||||
portLock[portId]->lockForRead();
|
||||
for (int i = 0; i < request->device_id_size(); i++)
|
||||
for (int i = 0; i < request->device_group_id_size(); i++)
|
||||
{
|
||||
Device *device;
|
||||
OstProto::Device *d;
|
||||
const OstProto::DeviceGroup *dg;
|
||||
|
||||
device = devMgr->device(request->device_id(i).id());
|
||||
if (!device)
|
||||
dg = devMgr->deviceGroup(request->device_group_id(i).id());
|
||||
if (!dg)
|
||||
continue; //! \todo(LOW): Partial status of RPC
|
||||
|
||||
d = response->add_device();
|
||||
device->protoDataCopyInto(*d);
|
||||
response->add_device_group()->CopyFrom(*dg);
|
||||
}
|
||||
portLock[portId]->unlock();
|
||||
|
||||
@ -677,8 +677,9 @@ _invalid_port:
|
||||
done->Run();
|
||||
}
|
||||
|
||||
void MyService::addDevice(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceIdList* request,
|
||||
void MyService::addDeviceGroup(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceGroupIdList* request,
|
||||
::OstProto::Ack* /*response*/,
|
||||
::google::protobuf::Closure* done)
|
||||
{
|
||||
@ -699,16 +700,16 @@ void MyService::addDevice(::google::protobuf::RpcController* controller,
|
||||
#endif
|
||||
|
||||
portLock[portId]->lockForWrite();
|
||||
for (int i = 0; i < request->device_id_size(); i++)
|
||||
for (int i = 0; i < request->device_group_id_size(); i++)
|
||||
{
|
||||
quint32 id = request->device_id(i).id();
|
||||
Device *device = devMgr->device(id);
|
||||
quint32 id = request->device_group_id(i).id();
|
||||
const OstProto::DeviceGroup *dg = devMgr->deviceGroup(id);
|
||||
|
||||
// If device with same id as in request exists already ==> error!!
|
||||
if (device)
|
||||
// If device group with same id as in request exists already ==> error!
|
||||
if (dg)
|
||||
continue; //! \todo (LOW): Partial status of RPC
|
||||
|
||||
devMgr->addDevice(id);
|
||||
devMgr->addDeviceGroup(id);
|
||||
}
|
||||
portLock[portId]->unlock();
|
||||
|
||||
@ -729,8 +730,9 @@ _exit:
|
||||
done->Run();
|
||||
}
|
||||
|
||||
void MyService::deleteDevice(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceIdList* request,
|
||||
void MyService::deleteDeviceGroup(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceGroupIdList* request,
|
||||
::OstProto::Ack* /*response*/,
|
||||
::google::protobuf::Closure* done)
|
||||
{
|
||||
@ -751,8 +753,8 @@ void MyService::deleteDevice(::google::protobuf::RpcController* controller,
|
||||
#endif
|
||||
|
||||
portLock[portId]->lockForWrite();
|
||||
for (int i = 0; i < request->device_id_size(); i++)
|
||||
devMgr->deleteDevice(request->device_id(i).id());
|
||||
for (int i = 0; i < request->device_group_id_size(); i++)
|
||||
devMgr->deleteDeviceGroup(request->device_group_id(i).id());
|
||||
portLock[portId]->unlock();
|
||||
|
||||
//! \todo (LOW): fill-in response "Ack"????
|
||||
@ -771,8 +773,9 @@ _exit:
|
||||
done->Run();
|
||||
}
|
||||
|
||||
void MyService::modifyDevice(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceConfigList* request,
|
||||
void MyService::modifyDeviceGroup(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceGroupConfigList* request,
|
||||
::OstProto::Ack* /*response*/,
|
||||
::google::protobuf::Closure* done)
|
||||
{
|
||||
@ -793,8 +796,8 @@ void MyService::modifyDevice(::google::protobuf::RpcController* controller,
|
||||
#endif
|
||||
|
||||
portLock[portId]->lockForWrite();
|
||||
for (int i = 0; i < request->device_size(); i++)
|
||||
devMgr->modifyDevice(&request->device(i));
|
||||
for (int i = 0; i < request->device_group_size(); i++)
|
||||
devMgr->modifyDeviceGroup(&request->device_group(i));
|
||||
portLock[portId]->unlock();
|
||||
|
||||
// FIXME: check for overlaps between devices?
|
||||
|
@ -105,25 +105,30 @@ public:
|
||||
::OstProto::VersionCompatibility* response,
|
||||
::google::protobuf::Closure* done);
|
||||
|
||||
// Device and Protocol Emulation
|
||||
virtual void getDeviceIdList(::google::protobuf::RpcController* controller,
|
||||
// DeviceGroup and Protocol Emulation
|
||||
virtual void getDeviceGroupIdList(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::PortId* request,
|
||||
::OstProto::DeviceIdList* response,
|
||||
::OstProto::DeviceGroupIdList* response,
|
||||
::google::protobuf::Closure* done);
|
||||
virtual void getDeviceConfig(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceIdList* request,
|
||||
::OstProto::DeviceConfigList* response,
|
||||
virtual void getDeviceGroupConfig(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceGroupIdList* request,
|
||||
::OstProto::DeviceGroupConfigList* response,
|
||||
::google::protobuf::Closure* done);
|
||||
virtual void addDevice(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceIdList* request,
|
||||
virtual void addDeviceGroup(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceGroupIdList* request,
|
||||
::OstProto::Ack* response,
|
||||
::google::protobuf::Closure* done);
|
||||
virtual void deleteDevice(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceIdList* request,
|
||||
virtual void deleteDeviceGroup(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceGroupIdList* request,
|
||||
::OstProto::Ack* response,
|
||||
::google::protobuf::Closure* done);
|
||||
virtual void modifyDevice(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceConfigList* request,
|
||||
virtual void modifyDeviceGroup(
|
||||
::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::DeviceGroupConfigList* request,
|
||||
::OstProto::Ack* response,
|
||||
::google::protobuf::Closure* done);
|
||||
signals:
|
||||
|
@ -139,54 +139,54 @@ try:
|
||||
# configure emulated device(s) on tx/rx ports #
|
||||
#---------------------------------------------#
|
||||
# delete existing devices, if any, on tx port
|
||||
did_list = drone.getDeviceIdList(tx_port.port_id[0])
|
||||
drone.deleteDevice(did_list)
|
||||
dgid_list = drone.getDeviceGroupIdList(tx_port.port_id[0])
|
||||
drone.deleteDeviceGroup(dgid_list)
|
||||
|
||||
# add a emulated device on tx port
|
||||
device_id = ost_pb.DeviceIdList()
|
||||
device_id.port_id.CopyFrom(tx_port.port_id[0])
|
||||
device_id.device_id.add().id = 1
|
||||
log.info('adding tx_device %d' % device_id.device_id[0].id)
|
||||
drone.addDevice(device_id)
|
||||
dgid_list = ost_pb.DeviceGroupIdList()
|
||||
dgid_list.port_id.CopyFrom(tx_port.port_id[0])
|
||||
dgid_list.device_group_id.add().id = 1
|
||||
log.info('adding tx device_group %d' % dgid_list.device_group_id[0].id)
|
||||
drone.addDeviceGroup(dgid_list)
|
||||
|
||||
# configure the device
|
||||
device_cfg = ost_pb.DeviceConfigList()
|
||||
device_cfg.port_id.CopyFrom(tx_port.port_id[0])
|
||||
d = device_cfg.device.add()
|
||||
d.device_id.id = device_id.device_id[0].id
|
||||
d.core.name = "Host1"
|
||||
d.Extensions[emul.mac].addr = 0x000102030001
|
||||
ip = d.Extensions[emul.ip4]
|
||||
ip.addr = 0x0a0a0164
|
||||
ip.prefix_length = 24
|
||||
ip.gateway = 0x0a0a0101
|
||||
devgrp_cfg = ost_pb.DeviceGroupConfigList()
|
||||
devgrp_cfg.port_id.CopyFrom(tx_port.port_id[0])
|
||||
dg = devgrp_cfg.device_group.add()
|
||||
dg.device_group_id.id = dgid_list.device_group_id[0].id
|
||||
dg.core.name = "Host1"
|
||||
d = dg.Extensions[emul.device]
|
||||
d.mac.address = 0x000102030001
|
||||
d.ip4.address = 0x0a0a0164
|
||||
d.ip4.prefix_length = 24
|
||||
d.ip4.default_gateway = 0x0a0a0101
|
||||
|
||||
drone.modifyDevice(device_cfg)
|
||||
drone.modifyDeviceGroup(devgrp_cfg)
|
||||
|
||||
# delete existing devices, if any, on rx port
|
||||
did_list = drone.getDeviceIdList(rx_port.port_id[0])
|
||||
drone.deleteDevice(did_list)
|
||||
dgid_list = drone.getDeviceGroupIdList(rx_port.port_id[0])
|
||||
drone.deleteDeviceGroup(dgid_list)
|
||||
|
||||
# add a emulated device on rx port
|
||||
device_id = ost_pb.DeviceIdList()
|
||||
device_id.port_id.CopyFrom(rx_port.port_id[0])
|
||||
device_id.device_id.add().id = 1
|
||||
log.info('adding rx_device %d' % device_id.device_id[0].id)
|
||||
drone.addDevice(device_id)
|
||||
dgid_list = ost_pb.DeviceGroupIdList()
|
||||
dgid_list.port_id.CopyFrom(rx_port.port_id[0])
|
||||
dgid_list.device_group_id.add().id = 1
|
||||
log.info('adding rx device_group %d' % dgid_list.device_group_id[0].id)
|
||||
drone.addDeviceGroup(dgid_list)
|
||||
|
||||
# configure the device
|
||||
device_cfg = ost_pb.DeviceConfigList()
|
||||
device_cfg.port_id.CopyFrom(rx_port.port_id[0])
|
||||
d = device_cfg.device.add()
|
||||
d.device_id.id = device_id.device_id[0].id
|
||||
d.core.name = "Host2"
|
||||
d.Extensions[emul.mac].addr = 0x000102030002
|
||||
ip = d.Extensions[emul.ip4]
|
||||
ip.addr = 0x0a0a0264
|
||||
ip.prefix_length = 24
|
||||
ip.gateway = 0x0a0a0201
|
||||
devgrp_cfg = ost_pb.DeviceGroupConfigList()
|
||||
devgrp_cfg.port_id.CopyFrom(rx_port.port_id[0])
|
||||
dg = devgrp_cfg.device_group.add()
|
||||
dg.device_group_id.id = dgid_list.device_group_id[0].id
|
||||
dg.core.name = "Host1"
|
||||
d = dg.Extensions[emul.device]
|
||||
d.mac.address = 0x000102030002
|
||||
d.ip4.address = 0x0a0a0264
|
||||
d.ip4.prefix_length = 24
|
||||
d.ip4.default_gateway = 0x0a0a0201
|
||||
|
||||
drone.modifyDevice(device_cfg)
|
||||
drone.modifyDeviceGroup(devgrp_cfg)
|
||||
|
||||
#--------------------------------------#
|
||||
# configure traffic stream(s)
|
||||
@ -210,7 +210,7 @@ try:
|
||||
s.core.is_enabled = True
|
||||
#s.core.frame_len = 128
|
||||
s.control.packets_per_sec = 20
|
||||
s.control.num_packets = 100
|
||||
s.control.num_packets = 10
|
||||
|
||||
# setup stream protocols as mac:eth2:ip4:udp:payload
|
||||
p = s.protocol.add()
|
||||
@ -280,10 +280,10 @@ try:
|
||||
drone.deleteStream(stream_id)
|
||||
|
||||
# delete devices
|
||||
did_list = drone.getDeviceIdList(tx_port.port_id[0])
|
||||
drone.deleteDevice(did_list)
|
||||
did_list = drone.getDeviceIdList(rx_port.port_id[0])
|
||||
drone.deleteDevice(did_list)
|
||||
dgid_list = drone.getDeviceGroupIdList(tx_port.port_id[0])
|
||||
drone.deleteDeviceGroup(dgid_list)
|
||||
dgid_list = drone.getDeviceGroupIdList(rx_port.port_id[0])
|
||||
drone.deleteDeviceGroup(dgid_list)
|
||||
|
||||
# bye for now
|
||||
drone.disconnect()
|
||||
|
Loading…
Reference in New Issue
Block a user