Feature (contd.): Device Emulation - added test cases for multiple ip4 devices with and without VLANs; fixed bugs discovered via these cases
This commit is contained in:
parent
246bc95c74
commit
0c98e30a93
@ -130,7 +130,7 @@ void Device::encap(PacketBuffer *pktBuf, quint64 dstMac, quint16 type)
|
||||
*(quint16*)(p + 10) = qToBigEndian(quint16(srcMac & 0xffff));
|
||||
ofs = 12;
|
||||
for (int i = 0; i < numVlanTags_; i++) {
|
||||
*(quint16*)(p + ofs) = qToBigEndian(quint32((0x8100 << 16)|vlan_[i]));
|
||||
*(quint32*)(p + ofs) = qToBigEndian(quint32((0x8100 << 16)|vlan_[i]));
|
||||
ofs += 4;
|
||||
}
|
||||
*(quint16*)(p + ofs) = qToBigEndian(type);
|
||||
@ -166,6 +166,8 @@ void Device::receivePacket(PacketBuffer *pktBuf)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// FIXME: temporary hack till DeviceManager clones pbufs
|
||||
pktBuf->push(2);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -169,7 +169,7 @@ _eth_type:
|
||||
vlan = qFromBigEndian<quint16>(pktData + offset);
|
||||
dk.setVlan(idx++, vlan);
|
||||
offset += 2;
|
||||
qDebug("%s: idx: %d vlan 0x%x", __FUNCTION__, idx, vlan);
|
||||
qDebug("%s: idx: %d vlan %d", __FUNCTION__, idx, vlan);
|
||||
goto _eth_type;
|
||||
}
|
||||
|
||||
@ -177,6 +177,11 @@ _eth_type:
|
||||
|
||||
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->receivePacket(pktBuf);
|
||||
goto _exit;
|
||||
@ -228,7 +233,7 @@ void DeviceManager::enumerateDevices(
|
||||
break;
|
||||
case OstEmul::VlanEmulation::kRepeat:
|
||||
default:
|
||||
vlanAdd %= vlan.count();
|
||||
vlanAdd %= vlan.step() * vlan.count();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -237,8 +242,8 @@ void DeviceManager::enumerateDevices(
|
||||
|
||||
for (uint k = 0; k < pbDevice.count(); k++) {
|
||||
Device *device;
|
||||
quint64 macAdd = i*k*pbDevice.mac().step();
|
||||
quint32 ip4Add = i*k*pbDevice.ip4().step();
|
||||
quint64 macAdd = (i*pbDevice.count()+k)*pbDevice.mac().step();
|
||||
quint32 ip4Add = (i*pbDevice.count()+k)*pbDevice.ip4().step();
|
||||
|
||||
switch (pbDevice.mode()) {
|
||||
case OstEmul::Device::kNoRepeat:
|
||||
@ -246,8 +251,8 @@ void DeviceManager::enumerateDevices(
|
||||
break;
|
||||
case OstEmul::Device::kRepeat:
|
||||
default:
|
||||
macAdd %= pbDevice.count();
|
||||
ip4Add %= pbDevice.count();
|
||||
macAdd %= pbDevice.mac().step() * pbDevice.count();
|
||||
ip4Add %= pbDevice.ip4().step() * pbDevice.count();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -265,12 +270,12 @@ void DeviceManager::enumerateDevices(
|
||||
|
||||
dk.setMac(kBcastMac);
|
||||
bcastList_.insert(dk.key(), device);
|
||||
qDebug("enumerate (add): %s", qPrintable(device->config()));
|
||||
qDebug("enumerate(add): %s", qPrintable(device->config()));
|
||||
break;
|
||||
|
||||
case kDelete:
|
||||
device = deviceList_.take(dk.key());
|
||||
qDebug("enumerate (del): %s", qPrintable(device->config()));
|
||||
qDebug("enumerate(del): %s", qPrintable(device->config()));
|
||||
delete device;
|
||||
|
||||
dk.setMac(kBcastMac);
|
||||
|
@ -918,6 +918,7 @@ void PcapPort::PortReceiver::run()
|
||||
int flag = PCAP_OPENFLAG_PROMISCUOUS;
|
||||
char errbuf[PCAP_ERRBUF_SIZE] = "";
|
||||
struct bpf_program bpf;
|
||||
const char *capture_filter = "arp or (vlan and arp)";
|
||||
const int optimize = 1;
|
||||
|
||||
qDebug("In %s", __PRETTY_FUNCTION__);
|
||||
@ -947,7 +948,7 @@ _retry:
|
||||
}
|
||||
|
||||
// FIXME: hardcoded filter
|
||||
if (pcap_compile(handle_, &bpf, "arp", optimize, 0) < 0)
|
||||
if (pcap_compile(handle_, &bpf, capture_filter, optimize, 0) < 0)
|
||||
{
|
||||
qWarning("%s: error compiling filter: %s", qPrintable(device_),
|
||||
pcap_geterr(handle_));
|
||||
|
477
test/emultest.py
477
test/emultest.py
@ -3,18 +3,20 @@
|
||||
# standard modules
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
from fabric.api import run, env, sudo
|
||||
from harness import Test, TestSuite
|
||||
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.ip4_pb2 import ip4, Ip4
|
||||
from protocols.vlan_pb2 import vlan
|
||||
|
||||
use_defaults = False
|
||||
|
||||
@ -22,7 +24,6 @@ use_defaults = False
|
||||
host_name = '127.0.0.1'
|
||||
tx_port_number = -1
|
||||
rx_port_number = -1
|
||||
#FIXME:drone_version = ['0', '0', '0']
|
||||
|
||||
if sys.platform == 'win32':
|
||||
tshark = r'C:\Program Files\Wireshark\tshark.exe'
|
||||
@ -70,19 +71,23 @@ suite = TestSuite()
|
||||
if not use_defaults:
|
||||
s = raw_input('Drone\'s Hostname/IP [%s]: ' % (host_name))
|
||||
host_name = s or host_name
|
||||
|
||||
drone = DroneProxy(host_name)
|
||||
|
||||
try:
|
||||
# ----------------------------------------------------------------- #
|
||||
# Baseline Configuration for subsequent testcases
|
||||
# NOTES
|
||||
# * All test cases will emulate devices on both rx and tx ports
|
||||
# * Each test case will create traffic streams corresponding to
|
||||
# the devices to check
|
||||
# ----------------------------------------------------------------- #
|
||||
|
||||
|
||||
# FIXME: get inputs for dut rx/tx ports
|
||||
|
||||
# configure the DUT
|
||||
# Enable IP forwarding on the DUT (aka make it a router)
|
||||
sudo('sysctl -w net.ipv4.ip_forward=1')
|
||||
sudo('ifconfig ' + dut_rx_port + ' 10.10.1.1 netmask 255.255.255.0')
|
||||
sudo('ifconfig ' + dut_tx_port + ' 10.10.2.1 netmask 255.255.255.0')
|
||||
|
||||
# connect to drone
|
||||
log.info('connecting to drone(%s:%d)'
|
||||
@ -135,62 +140,38 @@ try:
|
||||
rx_port = ost_pb.PortIdList()
|
||||
rx_port.port_id.add().id = rx_port_number;
|
||||
|
||||
#---------------------------------------------#
|
||||
# configure emulated device(s) on tx/rx ports #
|
||||
#---------------------------------------------#
|
||||
# ----------------------------------------------------------------- #
|
||||
# create emulated device(s) on tx/rx ports - each test case will
|
||||
# modify and reuse these devices as per its needs
|
||||
# ----------------------------------------------------------------- #
|
||||
|
||||
# delete existing devices, if any, on tx port
|
||||
dgid_list = drone.getDeviceGroupIdList(tx_port.port_id[0])
|
||||
drone.deleteDeviceGroup(dgid_list)
|
||||
tx_dgid_list = drone.getDeviceGroupIdList(tx_port.port_id[0])
|
||||
drone.deleteDeviceGroup(tx_dgid_list)
|
||||
|
||||
# add a emulated device on tx port
|
||||
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
|
||||
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.modifyDeviceGroup(devgrp_cfg)
|
||||
tx_dgid_list = ost_pb.DeviceGroupIdList()
|
||||
tx_dgid_list.port_id.CopyFrom(tx_port.port_id[0])
|
||||
tx_dgid_list.device_group_id.add().id = 1
|
||||
log.info('adding tx device_group %d' % tx_dgid_list.device_group_id[0].id)
|
||||
drone.addDeviceGroup(tx_dgid_list)
|
||||
|
||||
# delete existing devices, if any, on rx port
|
||||
dgid_list = drone.getDeviceGroupIdList(rx_port.port_id[0])
|
||||
drone.deleteDeviceGroup(dgid_list)
|
||||
rx_dgid_list = drone.getDeviceGroupIdList(rx_port.port_id[0])
|
||||
drone.deleteDeviceGroup(rx_dgid_list)
|
||||
|
||||
# add a emulated device on rx port
|
||||
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)
|
||||
rx_dgid_list = ost_pb.DeviceGroupIdList()
|
||||
rx_dgid_list.port_id.CopyFrom(rx_port.port_id[0])
|
||||
rx_dgid_list.device_group_id.add().id = 1
|
||||
log.info('adding rx device_group %d' % rx_dgid_list.device_group_id[0].id)
|
||||
drone.addDeviceGroup(rx_dgid_list)
|
||||
|
||||
# configure the device
|
||||
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
|
||||
# ----------------------------------------------------------------- #
|
||||
# create stream on tx port - each test case will modify and reuse
|
||||
# this stream as per its needs
|
||||
# ----------------------------------------------------------------- #
|
||||
|
||||
drone.modifyDeviceGroup(devgrp_cfg)
|
||||
|
||||
#--------------------------------------#
|
||||
# configure traffic stream(s)
|
||||
#--------------------------------------#
|
||||
# delete existing streams, if any, on tx port
|
||||
sid_list = drone.getStreamIdList(tx_port.port_id[0])
|
||||
drone.deleteStream(sid_list)
|
||||
@ -202,57 +183,109 @@ try:
|
||||
log.info('adding tx_stream %d' % stream_id.stream_id[0].id)
|
||||
drone.addStream(stream_id)
|
||||
|
||||
# configure the stream
|
||||
stream_cfg = ost_pb.StreamConfigList()
|
||||
stream_cfg.port_id.CopyFrom(tx_port.port_id[0])
|
||||
s = stream_cfg.stream.add()
|
||||
s.stream_id.id = stream_id.stream_id[0].id
|
||||
s.core.is_enabled = True
|
||||
#s.core.frame_len = 128
|
||||
s.control.packets_per_sec = 20
|
||||
s.control.num_packets = 10
|
||||
|
||||
# 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 = 0x0800278df2b4 #FIXME: hardcoding
|
||||
p.Extensions[mac].src_mac = 0x00aabbccddee
|
||||
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber
|
||||
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kIp4FieldNumber
|
||||
# reduce typing by creating a shorter reference to p.Extensions[ip4]
|
||||
ip = p.Extensions[ip4]
|
||||
ip.src_ip = 0x0a0a0164
|
||||
ip.dst_ip = 0x0a0a0264
|
||||
|
||||
s.protocol.add().protocol_id.id = ost_pb.Protocol.kUdpFieldNumber
|
||||
s.protocol.add().protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber
|
||||
|
||||
log.info('configuring tx_stream %d' % stream_id.stream_id[0].id)
|
||||
drone.modifyStream(stream_cfg)
|
||||
|
||||
# all test cases will use this stream by modifying it as per its needs
|
||||
|
||||
# clear tx/rx stats
|
||||
log.info('clearing tx/rx stats')
|
||||
drone.clearStats(tx_port)
|
||||
drone.clearStats(rx_port)
|
||||
# ================================================================= #
|
||||
# ----------------------------------------------------------------- #
|
||||
# TEST CASES
|
||||
# ----------------------------------------------------------------- #
|
||||
# ================================================================= #
|
||||
|
||||
# ----------------------------------------------------------------- #
|
||||
# TESTCASE: FIXME
|
||||
# TESTCASE: Emulate multiple IPv4 devices (no vlans)
|
||||
# DUT
|
||||
# /.1 \.1
|
||||
# / \
|
||||
# 10.10.1/24 10.10.2/24
|
||||
# / \
|
||||
# /.101-105 \.101-105
|
||||
# Host1(s) Host2(s)
|
||||
# ----------------------------------------------------------------- #
|
||||
|
||||
passed = False
|
||||
suite.test_begin('startTransmitDuringTransmitIsNopNotRestart')
|
||||
# clear arp on DUT
|
||||
sudo('arp -d ' + '10.10.1.100', warn_only=True)
|
||||
sudo('arp -d ' + '10.10.2.100', warn_only=True)
|
||||
run('arp -a')
|
||||
drone.startCapture(rx_port)
|
||||
drone.startTransmit(tx_port)
|
||||
suite.test_begin('multiEmulDev')
|
||||
|
||||
num_devs = 5
|
||||
try:
|
||||
# configure the DUT
|
||||
sudo('ip address add 10.10.1.1/24 dev ' + dut_rx_port)
|
||||
sudo('ip address add 10.10.2.1/24 dev ' + dut_tx_port)
|
||||
|
||||
# configure the tx device(s)
|
||||
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 = tx_dgid_list.device_group_id[0].id
|
||||
dg.core.name = "Host1"
|
||||
d = dg.Extensions[emul.device]
|
||||
d.count = num_devs
|
||||
d.mac.address = 0x000102030a01
|
||||
d.ip4.address = 0x0a0a0165
|
||||
d.ip4.prefix_length = 24
|
||||
d.ip4.default_gateway = 0x0a0a0101
|
||||
|
||||
drone.modifyDeviceGroup(devgrp_cfg)
|
||||
|
||||
# configure the rx device(s)
|
||||
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 = rx_dgid_list.device_group_id[0].id
|
||||
dg.core.name = "Host1"
|
||||
d = dg.Extensions[emul.device]
|
||||
d.count = num_devs
|
||||
d.mac.address = 0x000102030b01
|
||||
d.ip4.address = 0x0a0a0265
|
||||
d.ip4.prefix_length = 24
|
||||
d.ip4.default_gateway = 0x0a0a0201
|
||||
|
||||
drone.modifyDeviceGroup(devgrp_cfg)
|
||||
|
||||
# configure the tx stream
|
||||
stream_cfg = ost_pb.StreamConfigList()
|
||||
stream_cfg.port_id.CopyFrom(tx_port.port_id[0])
|
||||
s = stream_cfg.stream.add()
|
||||
s.stream_id.id = stream_id.stream_id[0].id
|
||||
s.core.is_enabled = True
|
||||
s.control.packets_per_sec = 20
|
||||
s.control.num_packets = 10
|
||||
|
||||
# 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 = 0x0800278df2b4 #FIXME: hardcoding
|
||||
p.Extensions[mac].src_mac = 0x00aabbccddee
|
||||
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber
|
||||
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kIp4FieldNumber
|
||||
ip = p.Extensions[ip4]
|
||||
ip.src_ip = 0x0a0a0165
|
||||
ip.src_ip_mode = Ip4.e_im_inc_host
|
||||
ip.src_ip_count = num_devs
|
||||
ip.dst_ip = 0x0a0a0265
|
||||
ip.dst_ip_mode = Ip4.e_im_inc_host
|
||||
ip.dst_ip_count = num_devs
|
||||
|
||||
s.protocol.add().protocol_id.id = ost_pb.Protocol.kUdpFieldNumber
|
||||
s.protocol.add().protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber
|
||||
|
||||
log.info('configuring tx_stream %d' % stream_id.stream_id[0].id)
|
||||
drone.modifyStream(stream_cfg)
|
||||
|
||||
# clear tx/rx stats
|
||||
log.info('clearing tx/rx stats')
|
||||
drone.clearStats(tx_port)
|
||||
drone.clearStats(rx_port)
|
||||
|
||||
# clear arp on DUT
|
||||
sudo('ip neigh flush all')
|
||||
arp_cache = run('ip neigh show')
|
||||
if re.search('10.10.2.10[1-5].*lladdr', arp_cache):
|
||||
raise TestPreRequisiteError('ARP cache not cleared')
|
||||
|
||||
drone.startCapture(rx_port)
|
||||
drone.startTransmit(tx_port)
|
||||
log.info('waiting for transmit to finish ...')
|
||||
time.sleep(7)
|
||||
drone.stopTransmit(tx_port)
|
||||
@ -260,26 +293,261 @@ try:
|
||||
|
||||
buff = drone.getCaptureBuffer(rx_port.port_id[0])
|
||||
drone.saveCaptureBuffer(buff, 'capture.pcap')
|
||||
log.info('dumping Rx capture buffer')
|
||||
cap_pkts = subprocess.check_output([tshark, '-r', 'capture.pcap'])
|
||||
log.info('dumping Rx capture buffer (all)')
|
||||
cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap'])
|
||||
print(cap_pkts)
|
||||
if '10.10.2.100' in cap_pkts:
|
||||
log.info('dumping Rx capture buffer (filtered)')
|
||||
fail = 0
|
||||
for i in range(num_devs):
|
||||
cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap',
|
||||
'-R', '(ip.src == 10.10.1.' + str(101+i) + ') '
|
||||
' && (ip.dst == 10.10.2.' + str(101+i) + ')'
|
||||
' && (eth.dst == 00:01:02:03:0b:'
|
||||
+ format(1+i, '02x')+')'])
|
||||
print(cap_pkts)
|
||||
if cap_pkts.count('\n') != s.control.num_packets/ip.src_ip_count:
|
||||
fail = fail + 1
|
||||
if fail == 0:
|
||||
passed = True
|
||||
os.remove('capture.pcap')
|
||||
except RpcError as e:
|
||||
raise
|
||||
finally:
|
||||
drone.stopTransmit(tx_port)
|
||||
run('arp -a')
|
||||
run('ip neigh show')
|
||||
# unconfigure DUT
|
||||
sudo('ip address delete 10.10.1.1/24 dev ' + dut_rx_port)
|
||||
sudo('ip address delete 10.10.2.1/24 dev ' + dut_tx_port)
|
||||
suite.test_end(passed)
|
||||
|
||||
# ----------------------------------------------------------------- #
|
||||
# TESTCASE: Emulate multiple IPv4 device per multiple single-tag VLANs
|
||||
#
|
||||
# +- DUT -+
|
||||
# .1/ \.1
|
||||
# / \
|
||||
# 10.1.1/24 10.1.2/24
|
||||
# v[201-205] v[201-205]
|
||||
# / \
|
||||
# /.101-103 \.101-103
|
||||
# Host1(s) Host2(s)
|
||||
# ----------------------------------------------------------------- #
|
||||
|
||||
passed = False
|
||||
suite.test_begin('multiEmulDevPerVlan')
|
||||
|
||||
num_vlans = 5
|
||||
vlan_base = 201
|
||||
num_devs = 3
|
||||
dev_ip_base = 101
|
||||
try:
|
||||
# configure the DUT
|
||||
for i in range(num_vlans):
|
||||
vlan_id = vlan_base+i
|
||||
vrf = 'v' + str(vlan_id)
|
||||
vlan_rx_dev = dut_rx_port + '.' + str(vlan_id)
|
||||
vlan_tx_dev = dut_tx_port + '.' + str(vlan_id)
|
||||
|
||||
sudo('ip netns add ' + vrf)
|
||||
|
||||
sudo('ip link add link ' + dut_rx_port
|
||||
+ ' name ' + vlan_rx_dev
|
||||
+ ' type vlan id ' + str(vlan_id))
|
||||
sudo('ip link set ' + vlan_rx_dev
|
||||
+ ' netns ' + vrf)
|
||||
sudo('ip netns exec ' + vrf
|
||||
+ ' ip addr add 10.1.1.1/24'
|
||||
+ ' dev ' + vlan_rx_dev)
|
||||
sudo('ip netns exec ' + vrf
|
||||
+ ' ip link set ' + vlan_rx_dev + ' up')
|
||||
|
||||
sudo('ip link add link ' + dut_tx_port
|
||||
+ ' name ' + vlan_tx_dev
|
||||
+ ' type vlan id ' + str(vlan_id))
|
||||
sudo('ip link set ' + vlan_tx_dev
|
||||
+ ' netns ' + vrf)
|
||||
sudo('ip netns exec ' + vrf
|
||||
+ ' ip addr add 10.1.2.1/24'
|
||||
+ ' dev ' + vlan_tx_dev)
|
||||
sudo('ip netns exec ' + vrf
|
||||
+ ' ip link set ' + vlan_tx_dev + ' up')
|
||||
|
||||
|
||||
# configure the tx device(s)
|
||||
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 = tx_dgid_list.device_group_id[0].id
|
||||
dg.core.name = "Host1"
|
||||
v = dg.Extensions[emul.vlan].stack.add()
|
||||
v.vlan_tag = vlan_base
|
||||
v.count = num_vlans
|
||||
d = dg.Extensions[emul.device]
|
||||
d.count = num_devs
|
||||
d.mac.address = 0x000102030a01
|
||||
d.ip4.address = 0x0a010165
|
||||
d.ip4.prefix_length = 24
|
||||
d.ip4.default_gateway = 0x0a0a0101
|
||||
|
||||
drone.modifyDeviceGroup(devgrp_cfg)
|
||||
|
||||
# configure the rx device(s)
|
||||
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 = rx_dgid_list.device_group_id[0].id
|
||||
dg.core.name = "Host1"
|
||||
v = dg.Extensions[emul.vlan].stack.add()
|
||||
v.vlan_tag = vlan_base
|
||||
v.count = num_vlans
|
||||
d = dg.Extensions[emul.device]
|
||||
d.count = num_devs
|
||||
#d.mode = emul.Device.kNoRepeat
|
||||
d.mac.address = 0x000102030b01
|
||||
d.ip4.address = 0x0a010265
|
||||
d.ip4.prefix_length = 24
|
||||
d.ip4.default_gateway = 0x0a0a0201
|
||||
|
||||
drone.modifyDeviceGroup(devgrp_cfg)
|
||||
|
||||
# configure the tx stream(s)
|
||||
# we need more than one stream, so delete old one
|
||||
# and create as many as we need
|
||||
# FIXME: restore the single stream at end?
|
||||
log.info('deleting tx_stream %d' % stream_id.stream_id[0].id)
|
||||
drone.deleteStream(stream_id)
|
||||
|
||||
stream_id = ost_pb.StreamIdList()
|
||||
stream_id.port_id.CopyFrom(tx_port.port_id[0])
|
||||
for i in range(num_vlans):
|
||||
stream_id.stream_id.add().id = i
|
||||
log.info('adding tx_stream %d' % stream_id.stream_id[i].id)
|
||||
|
||||
drone.addStream(stream_id)
|
||||
|
||||
stream_cfg = ost_pb.StreamConfigList()
|
||||
stream_cfg.port_id.CopyFrom(tx_port.port_id[0])
|
||||
for i in range(num_vlans):
|
||||
s = stream_cfg.stream.add()
|
||||
s.stream_id.id = stream_id.stream_id[i].id
|
||||
s.core.is_enabled = True
|
||||
s.core.ordinal = i
|
||||
s.control.packets_per_sec = 10
|
||||
s.control.num_packets = num_devs
|
||||
|
||||
# setup stream protocols as mac:vlan:eth2:ip4:udp:payload
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kMacFieldNumber
|
||||
p.Extensions[mac].dst_mac = 0x0800278df2b4 #FIXME: hardcoding
|
||||
p.Extensions[mac].src_mac = 0x00aabbccddee
|
||||
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kVlanFieldNumber
|
||||
p.Extensions[vlan].vlan_tag = vlan_base+i
|
||||
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber
|
||||
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kIp4FieldNumber
|
||||
ip = p.Extensions[ip4]
|
||||
ip.src_ip = 0x0a010165
|
||||
ip.src_ip_mode = Ip4.e_im_inc_host
|
||||
ip.dst_ip = 0x0a010265
|
||||
ip.dst_ip_mode = Ip4.e_im_inc_host
|
||||
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kUdpFieldNumber
|
||||
p = s.protocol.add()
|
||||
p.protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber
|
||||
|
||||
log.info('configuring tx_stream %d' % stream_id.stream_id[0].id)
|
||||
|
||||
drone.modifyStream(stream_cfg)
|
||||
|
||||
# clear tx/rx stats
|
||||
log.info('clearing tx/rx stats')
|
||||
drone.clearStats(tx_port)
|
||||
drone.clearStats(rx_port)
|
||||
|
||||
# clear arp on DUT
|
||||
for i in range(num_vlans):
|
||||
vlan_id = vlan_base + i
|
||||
vrf = 'v' + str(vlan_id)
|
||||
vlan_rx_dev = dut_rx_port + '.' + str(vlan_id)
|
||||
vlan_tx_dev = dut_tx_port + '.' + str(vlan_id)
|
||||
|
||||
sudo('ip netns exec ' + vrf
|
||||
+ ' ip neigh flush dev ' + vlan_rx_dev)
|
||||
sudo('ip netns exec ' + vrf
|
||||
+ ' ip neigh flush dev ' + vlan_tx_dev)
|
||||
sudo('ip netns exec ' + vrf
|
||||
+ ' ip neigh show')
|
||||
|
||||
drone.startCapture(rx_port)
|
||||
drone.startTransmit(tx_port)
|
||||
log.info('waiting for transmit to finish ...')
|
||||
time.sleep(5)
|
||||
drone.stopTransmit(tx_port)
|
||||
drone.stopCapture(rx_port)
|
||||
|
||||
buff = drone.getCaptureBuffer(rx_port.port_id[0])
|
||||
drone.saveCaptureBuffer(buff, 'capture.pcap')
|
||||
log.info('dumping Rx capture buffer (all)')
|
||||
cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap'])
|
||||
print(cap_pkts)
|
||||
log.info('dumping Rx capture buffer (filtered)')
|
||||
fail = 0
|
||||
for i in range(num_vlans):
|
||||
for j in range(num_devs):
|
||||
cap_pkts = subprocess.check_output(
|
||||
[tshark, '-nr', 'capture.pcap',
|
||||
'-R', '(vlan.id == ' + str(201+i) + ')'
|
||||
' && (ip.src == 10.1.1.' + str(101+j) + ') '
|
||||
' && (ip.dst == 10.1.2.' + str(101+j) + ')'
|
||||
' && (eth.dst == 00:01:02:03:0b:'
|
||||
+ format(1+j, '02x')+')'])
|
||||
print(cap_pkts)
|
||||
if cap_pkts.count('\n') != 1:
|
||||
fail = fail + 1
|
||||
if fail == 0:
|
||||
passed = True
|
||||
os.remove('capture.pcap')
|
||||
except RpcError as e:
|
||||
raise
|
||||
finally:
|
||||
drone.stopTransmit(tx_port)
|
||||
# show arp on DUT
|
||||
for i in range(num_vlans):
|
||||
vrf = 'v' + str(vlan_base + i)
|
||||
sudo('ip netns exec ' + vrf
|
||||
+ ' ip neigh show')
|
||||
# un-configure the DUT
|
||||
for i in range(num_vlans):
|
||||
vlan_id = vlan_base + i
|
||||
vrf = 'v' + str(vlan_id)
|
||||
sudo('ip netns delete ' + vrf)
|
||||
suite.test_end(passed)
|
||||
|
||||
# TODO:
|
||||
# ----------------------------------------------------------------- #
|
||||
# TESTCASE: Emulate one IPv4 device per multiple double-tag VLANs
|
||||
# vlanMode: repeat (default)
|
||||
# TESTCASE: Emulate multiple IPv4 devices per multiple double-tag VLANs
|
||||
# vlanMode: no-repeat; ip4Mode: repeat (default)
|
||||
# TESTCASE: Emulate multiple IPv4 devices per multiple quad-tag VLANs
|
||||
# vlanMode: repeat (default); ip4Mode: repeat (default)
|
||||
# TESTCASE: Emulate multiple IPv4 devices per multiple quad-tag VLANs
|
||||
# vlanMode: no-repeat; ip4Mode: no-repeat
|
||||
# ----------------------------------------------------------------- #
|
||||
|
||||
suite.complete()
|
||||
|
||||
# delete streams
|
||||
# delete stream(s)
|
||||
log.info('deleting tx_stream %d' % stream_id.stream_id[0].id)
|
||||
drone.deleteStream(stream_id)
|
||||
|
||||
# delete devices
|
||||
# delete device(s)
|
||||
dgid_list = drone.getDeviceGroupIdList(tx_port.port_id[0])
|
||||
drone.deleteDeviceGroup(dgid_list)
|
||||
dgid_list = drone.getDeviceGroupIdList(rx_port.port_id[0])
|
||||
@ -287,6 +555,7 @@ try:
|
||||
|
||||
# bye for now
|
||||
drone.disconnect()
|
||||
#disconnect_all()
|
||||
|
||||
except Exception as ex:
|
||||
log.exception(ex)
|
||||
|
@ -46,6 +46,12 @@ class TestSuite:
|
||||
def passed(self):
|
||||
return passed == total and self.completed
|
||||
|
||||
class TestPreRequisiteError(Exception):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
def extract_column(text, col):
|
||||
"""Given a text table, return items in the specified column as a list"""
|
||||
lines = text.splitlines()
|
||||
|
Loading…
Reference in New Issue
Block a user