From 0c98e30a93d895fe7d19f2c6cd6810180a4f5d33 Mon Sep 17 00:00:00 2001 From: Srivats P Date: Sat, 3 Oct 2015 13:18:44 +0530 Subject: [PATCH] Feature (contd.): Device Emulation - added test cases for multiple ip4 devices with and without VLANs; fixed bugs discovered via these cases --- server/device.cpp | 4 +- server/devicemanager.cpp | 21 +- server/pcapport.cpp | 3 +- test/emultest.py | 477 ++++++++++++++++++++++++++++++--------- test/harness.py | 6 + 5 files changed, 397 insertions(+), 114 deletions(-) diff --git a/server/device.cpp b/server/device.cpp index a487074..3381e82 100644 --- a/server/device.cpp +++ b/server/device.cpp @@ -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); } // diff --git a/server/devicemanager.cpp b/server/devicemanager.cpp index 87cb40c..39681d7 100644 --- a/server/devicemanager.cpp +++ b/server/devicemanager.cpp @@ -169,7 +169,7 @@ _eth_type: vlan = qFromBigEndian(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 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); diff --git a/server/pcapport.cpp b/server/pcapport.cpp index 81c6c50..a7078e9 100644 --- a/server/pcapport.cpp +++ b/server/pcapport.cpp @@ -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_)); diff --git a/test/emultest.py b/test/emultest.py index 20275ed..7039dff 100644 --- a/test/emultest.py +++ b/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) diff --git a/test/harness.py b/test/harness.py index e6c2c92..7eb1b27 100644 --- a/test/harness.py +++ b/test/harness.py @@ -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()