Feature (contd.): Device Emulation - added getDeviceList() RPC

This commit is contained in:
Srivats P 2015-11-11 13:05:15 +05:30
parent 492a207ede
commit 7daf75c95a
9 changed files with 101 additions and 21 deletions

View File

@ -83,24 +83,21 @@ extend OstProto.DeviceGroup {
optional Ip6Emulation ip6 = 3001; optional Ip6Emulation ip6 = 3001;
} }
/* TODO
message Device { message Device {
optional uint64 mac = 1; optional uint64 mac = 1;
// FIXME: move vlan into encapInfo?
repeated uint32 vlan = 2; // includes tpid 'n vlan tag repeated uint32 vlan = 2; // includes tpid 'n vlan tag
optional uint32 ip4 = 3; optional uint32 ip4 = 10;
optional uint32 ip4_prefix_length = 4; optional uint32 ip4_prefix_length = 11;
optional uint32 ip4_default_gateway = 5; optional uint32 ip4_default_gateway = 12;
// TODO: IPv6 fields // TODO: IPv6 fields
} }
message DeviceList { extend OstProto.PortDeviceList {
repeated Device devices = 1; repeated Device port_device = 100;
} }
*/
message ArpEntry { message ArpEntry {
optional uint32 ip4 = 1; optional uint32 ip4 = 1;
@ -120,5 +117,6 @@ message DeviceNeighborList {
} }
extend OstProto.PortNeighborList { extend OstProto.PortNeighborList {
// FIXME: rename to device (singular) to be consistent with naming convention for other repeated fields
repeated DeviceNeighborList devices = 100; repeated DeviceNeighborList devices = 100;
} }

View File

@ -281,6 +281,8 @@ message Notification {
* FIXME: What will be the contents of a default device created by addDeviceGroup()? * FIXME: What will be the contents of a default device created by addDeviceGroup()?
* FIXME: decide default values for device and protoEmulations * FIXME: decide default values for device and protoEmulations
* FIXME: rename 'DeviceGroup'? * FIXME: rename 'DeviceGroup'?
* FIXME: merge getDeviceList() and get DeviceNeighbors() into a single
* getDeviceInfo() RPC?
*/ */
message DeviceGroupId { message DeviceGroupId {
required uint32 id = 1; required uint32 id = 1;
@ -308,6 +310,12 @@ message DeviceGroupConfigList {
repeated DeviceGroup device_group = 2; repeated DeviceGroup device_group = 2;
} }
message PortDeviceList {
required PortId port_id = 1;
extensions 100 to 199;
}
message PortNeighborList { message PortNeighborList {
required PortId port_id = 1; required PortId port_id = 1;
@ -344,7 +352,7 @@ service OstService {
rpc deleteDeviceGroup(DeviceGroupIdList) returns (Ack); rpc deleteDeviceGroup(DeviceGroupIdList) returns (Ack);
rpc modifyDeviceGroup(DeviceGroupConfigList) returns (Ack); rpc modifyDeviceGroup(DeviceGroupConfigList) returns (Ack);
// TODO: rpc getDeviceList(PortId) returns (DeviceList); rpc getDeviceList(PortId) returns (PortDeviceList);
rpc resolveDeviceNeighbors(PortIdList) returns (Ack); rpc resolveDeviceNeighbors(PortIdList) returns (Ack);
rpc clearDeviceNeighbors(PortIdList) returns (Ack); rpc clearDeviceNeighbors(PortIdList) returns (Ack);

View File

@ -27,7 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include <qendian.h> #include <qendian.h>
const int kBaseHex = 16; const int kBaseHex = 16;
const int kMaxVlan = 4;
const quint64 kBcastMac = 0xffffffffffffULL; const quint64 kBcastMac = 0xffffffffffffULL;
/* /*
@ -92,6 +91,17 @@ void Device::setIp4(quint32 address, int prefixLength, quint32 gateway)
ip4Gateway_ = gateway; ip4Gateway_ = gateway;
} }
void Device::getConfig(OstEmul::Device *deviceConfig)
{
for (int i = 0; i < numVlanTags_; i++)
deviceConfig->add_vlan(vlan_[i]);
deviceConfig->set_mac(mac_);
deviceConfig->set_ip4(ip4_);
deviceConfig->set_ip4_prefix_length(ip4PrefixLength_);
deviceConfig->set_ip4_default_gateway(ip4Gateway_);
}
QString Device::config() QString Device::config()
{ {
return QString("<vlans=%1/%2/%3/%4 mac=%5 ip4=%6/%7>") return QString("<vlans=%1/%2/%3/%4 mac=%5 ip4=%6/%7>")

View File

@ -40,6 +40,7 @@ public:
quint64 mac(); 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);
void getConfig(OstEmul::Device *deviceConfig);
QString config(); QString config();
DeviceKey key(); DeviceKey key();
@ -63,10 +64,12 @@ private: // methods
void sendArpRequest(PacketBuffer *pktBuf); void sendArpRequest(PacketBuffer *pktBuf);
private: // data private: // data
static const int kMaxVlan = 4;
DeviceManager *deviceManager_; DeviceManager *deviceManager_;
int numVlanTags_; int numVlanTags_;
quint16 vlan_[4]; // FIXME: vlan tpid quint16 vlan_[kMaxVlan]; // FIXME: vlan tpid
quint64 mac_; quint64 mac_;
quint32 ip4_; quint32 ip4_;
int ip4PrefixLength_; int ip4PrefixLength_;

View File

@ -134,6 +134,18 @@ int DeviceManager::deviceCount()
return deviceList_.size(); return deviceList_.size();
} }
void DeviceManager::getDeviceList(
OstProto::PortDeviceList *deviceList)
{
int count = 0;
foreach(Device *device, deviceList_) {
OstEmul::Device *dev =
deviceList->AddExtension(OstEmul::port_device);
device->getConfig(dev);
}
}
void DeviceManager::receivePacket(PacketBuffer *pktBuf) void DeviceManager::receivePacket(PacketBuffer *pktBuf)
{ {
uchar *pktData = pktBuf->data(); uchar *pktData = pktBuf->data();

View File

@ -47,6 +47,7 @@ public:
bool modifyDeviceGroup(const OstProto::DeviceGroup *deviceGroup); bool modifyDeviceGroup(const OstProto::DeviceGroup *deviceGroup);
int deviceCount(); int deviceCount();
void getDeviceList(OstProto::PortDeviceList *deviceList);
void receivePacket(PacketBuffer *pktBuf); void receivePacket(PacketBuffer *pktBuf);
void transmitPacket(PacketBuffer *pktBuf); void transmitPacket(PacketBuffer *pktBuf);
@ -57,6 +58,7 @@ public:
quint64 deviceMacAddress(PacketBuffer *pktBuf); quint64 deviceMacAddress(PacketBuffer *pktBuf);
quint64 neighborMacAddress(PacketBuffer *pktBuf); quint64 neighborMacAddress(PacketBuffer *pktBuf);
private: private:
enum Operation { kAdd, kDelete }; enum Operation { kAdd, kDelete };

View File

@ -823,6 +823,36 @@ _exit:
done->Run(); done->Run();
} }
void MyService::getDeviceList(
::google::protobuf::RpcController* controller,
const ::OstProto::PortId* request,
::OstProto::PortDeviceList* response,
::google::protobuf::Closure* done)
{
DeviceManager *devMgr;
int portId;
qDebug("In %s", __PRETTY_FUNCTION__);
portId = request->id();
if ((portId < 0) || (portId >= portInfo.size()))
goto _invalid_port;
devMgr = portInfo[portId]->deviceManager();
response->mutable_port_id()->set_id(portId);
portLock[portId]->lockForRead();
devMgr->getDeviceList(response);
portLock[portId]->unlock();
done->Run();
return;
_invalid_port:
controller->SetFailed("Invalid Port Id");
done->Run();
}
void MyService::resolveDeviceNeighbors( void MyService::resolveDeviceNeighbors(
::google::protobuf::RpcController* controller, ::google::protobuf::RpcController* controller,
const ::OstProto::PortIdList* request, const ::OstProto::PortIdList* request,
@ -905,6 +935,12 @@ _invalid_port:
done->Run(); done->Run();
} }
/*
* ===================================================================
* Friends
* TODO: Encap these global functions into a DeviceBroker singleton?
* ===================================================================
*/
quint64 getDeviceMacAddress(int portId, int streamId, int frameIndex) quint64 getDeviceMacAddress(int portId, int streamId, int frameIndex)
{ {
MyService *service = drone->rpcService(); MyService *service = drone->rpcService();

View File

@ -132,6 +132,12 @@ public:
::OstProto::Ack* response, ::OstProto::Ack* response,
::google::protobuf::Closure* done); ::google::protobuf::Closure* done);
virtual void getDeviceList(
::google::protobuf::RpcController* controller,
const ::OstProto::PortId* request,
::OstProto::PortDeviceList* response,
::google::protobuf::Closure* done);
virtual void resolveDeviceNeighbors( virtual void resolveDeviceNeighbors(
::google::protobuf::RpcController* controller, ::google::protobuf::RpcController* controller,
const ::OstProto::PortIdList* request, const ::OstProto::PortIdList* request,

View File

@ -257,8 +257,6 @@ try:
drone.modifyDeviceGroup(devgrp_cfg) drone.modifyDeviceGroup(devgrp_cfg)
s = raw_input('Press [Enter] to continue')
# configure the tx stream # configure the tx stream
stream_cfg = ost_pb.StreamConfigList() stream_cfg = ost_pb.StreamConfigList()
stream_cfg.port_id.CopyFrom(tx_port.port_id[0]) stream_cfg.port_id.CopyFrom(tx_port.port_id[0])
@ -348,29 +346,36 @@ try:
# retrieve and verify ARP Table on tx/rx ports # retrieve and verify ARP Table on tx/rx ports
log.info('retrieving ARP entries on tx port') log.info('retrieving ARP entries on tx port')
device_list = drone.getDeviceList(emul_ports.port_id[0])
device_config = device_list.Extensions[emul.port_device]
neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[0]) neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[0])
devices = neigh_list.Extensions[emul.devices] devices = neigh_list.Extensions[emul.devices]
# TODO: verify gateway IP is resolved for each device
# FIXME: needs device ip as part of neigh_list
log.info('ARP Table on tx port') log.info('ARP Table on tx port')
for device in devices: for dev_cfg, device in zip(device_config, devices):
resolved = False
for arp in device.arp: for arp in device.arp:
# TODO: pretty print ip and mac # TODO: pretty print ip and mac
print('%d: %08x %012x' % print('%08x: %08x %012x' %
(device.device_index, arp.ip4, arp.mac)) (dev_cfg.ip4, arp.ip4, arp.mac))
if (arp.ip4 == dev_cfg.ip4_default_gateway) and (arp.mac):
resolved = True
if not resolved:
fail = fail + 1
log.info('retrieving ARP entries on rx port') log.info('retrieving ARP entries on rx port')
device_list = drone.getDeviceList(emul_ports.port_id[0])
device_config = device_list.Extensions[emul.port_device]
neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[1]) neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[1])
devices = neigh_list.Extensions[emul.devices] devices = neigh_list.Extensions[emul.devices]
log.info('ARP Table on rx port') log.info('ARP Table on rx port')
for device in devices: for dev_cfg, device in zip(device_config, devices):
# verify *no* ARPs learnt on rx port # verify *no* ARPs learnt on rx port
if len(device.arp): if len(device.arp):
fail = fail + 1 fail = fail + 1
for arp in device.arp: for arp in device.arp:
# TODO: pretty print ip and mac # TODO: pretty print ip and mac
print('%d: %08x %012x' % print('%08x: %08x %012x' %
(device.device_index, arp.ip4, arp.mac)) (dev_cfg.ip4, arp.ip4, arp.mac))
drone.startCapture(rx_port) drone.startCapture(rx_port)
drone.startTransmit(tx_port) drone.startTransmit(tx_port)