diff options
-rw-r--r-- | conf/04_vnf.conf | 28 | ||||
-rw-r--r-- | core/traffic_controller_rfc2544.py | 10 | ||||
-rw-r--r-- | core/vnf_controller.py | 5 | ||||
-rw-r--r-- | core/vswitch_controller.py | 7 | ||||
-rw-r--r-- | core/vswitch_controller_p2p.py | 5 | ||||
-rw-r--r-- | core/vswitch_controller_pvp.py | 5 | ||||
-rw-r--r-- | core/vswitch_controller_pvvp.py | 5 | ||||
-rw-r--r-- | docs/to-be-reorganized/NEWS.rst | 7 | ||||
-rw-r--r-- | docs/to-be-reorganized/quickstart.rst | 38 | ||||
-rw-r--r-- | testcases/testcase.py | 20 | ||||
-rw-r--r-- | tools/pkt_gen/ixnet/ixnetrfc2544.tcl | 18 | ||||
-rw-r--r-- | vnfs/qemu/qemu.py | 14 | ||||
-rw-r--r-- | vnfs/qemu/qemu_dpdk.py | 13 | ||||
-rw-r--r-- | vnfs/qemu/qemu_virtio_net.py | 115 | ||||
-rw-r--r-- | vnfs/vnf/vnf.py | 10 | ||||
-rw-r--r-- | vswitches/ovs_dpdk_vhost.py | 6 | ||||
-rw-r--r-- | vswitches/ovs_vanilla.py | 53 | ||||
-rw-r--r-- | vswitches/vswitch.py | 7 |
18 files changed, 331 insertions, 35 deletions
diff --git a/conf/04_vnf.conf b/conf/04_vnf.conf index 034e4108..52cc6ec1 100644 --- a/conf/04_vnf.conf +++ b/conf/04_vnf.conf @@ -79,5 +79,33 @@ GUEST_SMP = ['2', '2'] # For 2 VNFs you may use [(4,5), (6, 7)] GUEST_CORE_BINDING = [(6, 7), (9, 10)] +GUEST_START_TIMEOUT = 120 GUEST_OVS_DPDK_DIR = '/root/ovs_dpdk' OVS_DPDK_SHARE = '/mnt/ovs_dpdk_share' + +# IP addresses to use for Vanilla OVS PVP testing +# Consider using RFC 2544/3330 recommended IP addresses for benchmark testing. +# Network: 198.18.0.0/15 +# Netmask: 255.254.0.0 +# Broadcast: 198.19.255.255 +# First IP: 198.18.0.1 +# Last IP: 198.19.255.254 +# Hosts: 131070 +# + +# ARP entries for the IXIA ports and the bridge you are using: +VANILLA_TGEN_PORT1_IP = '1.1.1.10' +VANILLA_TGEN_PORT1_MAC = 'AA:BB:CC:DD:EE:FF' + +VANILLA_TGEN_PORT2_IP = '1.1.2.10' +VANILLA_TGEN_PORT2_MAC = 'AA:BB:CC:DD:EE:F0' + +VANILLA_BRIDGE_IP = ['1.1.1.5/16', '1.1.1.6/16'] + +VANILLA_NIC1_NAME = ['eth0', 'eth2'] +VANILLA_NIC2_NAME = ['eth1', 'eth3'] + +VANILLA_NIC1_IP_CIDR = ['192.168.1.2/24', '192.168.1.4/24'] +VANILLA_NIC2_IP_CIDR = ['192.168.1.3/24', '192.168.1.5/24'] + +VNF_AFFINITIZATION_ON = True diff --git a/core/traffic_controller_rfc2544.py b/core/traffic_controller_rfc2544.py index fa4a9c35..5659569f 100644 --- a/core/traffic_controller_rfc2544.py +++ b/core/traffic_controller_rfc2544.py @@ -49,7 +49,7 @@ class TrafficControllerRFC2544(ITrafficController, IResults): packet_sizes_cli = get_test_param('pkt_sizes') if packet_sizes_cli: self._packet_sizes = [int(x.strip()) - for x in packet_sizes_cli.split(',')] + for x in packet_sizes_cli.split(',')] else: self._packet_sizes = settings.getValue('TRAFFICGEN_PKT_SIZES') @@ -91,7 +91,13 @@ class TrafficControllerRFC2544(ITrafficController, IResults): str(self._traffic_gen_class)) for packet_size in self._packet_sizes: - traffic['l2'] = {'framesize': packet_size} + # Merge framesize with the default traffic definition + if 'l2' in traffic: + traffic['l2'] = dict(traffic['l2'], + **{'framesize': packet_size}) + else: + traffic['l2'] = {'framesize': packet_size} + if traffic['traffic_type'] == 'back2back': result = self._traffic_gen_class.send_rfc2544_back2back( traffic, trials=self._trials, diff --git a/core/vnf_controller.py b/core/vnf_controller.py index 3d3be040..3313e9e3 100644 --- a/core/vnf_controller.py +++ b/core/vnf_controller.py @@ -15,6 +15,7 @@ """ import logging +from vnfs.vnf.vnf import IVnf class VnfController(object): """VNF controller class @@ -33,6 +34,10 @@ class VnfController(object): :param vnf_class: The VNF class to be used. """ + # reset VNF ID counter for each testcase + IVnf.reset_vnf_counter() + + # setup controller with requested number of VNFs self._logger = logging.getLogger(__name__) self._vnf_class = vnf_class self._deployment_scenario = deployment_scenario.upper() diff --git a/core/vswitch_controller.py b/core/vswitch_controller.py index 619e1d8b..855de8b2 100644 --- a/core/vswitch_controller.py +++ b/core/vswitch_controller.py @@ -49,3 +49,10 @@ class IVswitchController(object): raise NotImplementedError( "The VswitchController does not implement the \"get_ports_info\" " "function.") + + def dump_vswitch_flows(self): + """ Dumps flows from vswitch + """ + raise NotImplementedError( + "The VswitchController does not implement the " + "\"dump_vswitch_flows\" function.") diff --git a/core/vswitch_controller_p2p.py b/core/vswitch_controller_p2p.py index c15f7ef8..35600e1b 100644 --- a/core/vswitch_controller_p2p.py +++ b/core/vswitch_controller_p2p.py @@ -114,3 +114,8 @@ class VswitchControllerP2P(IVswitchController): """ self._logger.debug('get_ports_info using ' + str(self._vswitch_class)) return self._vswitch.get_ports(settings.getValue('VSWITCH_BRIDGE_NAME')) + + def dump_vswitch_flows(self): + """See IVswitchController for description + """ + self._vswitch.dump_flows(settings.getValue('VSWITCH_BRIDGE_NAME')) diff --git a/core/vswitch_controller_pvp.py b/core/vswitch_controller_pvp.py index 80c0fdb2..b2337bd6 100644 --- a/core/vswitch_controller_pvp.py +++ b/core/vswitch_controller_pvp.py @@ -104,3 +104,8 @@ class VswitchControllerPVP(IVswitchController): """ self._logger.debug('get_ports_info using ' + str(self._vswitch_class)) return self._vswitch.get_ports(settings.getValue('VSWITCH_BRIDGE_NAME')) + + def dump_vswitch_flows(self): + """See IVswitchController for description + """ + self._vswitch.dump_flows(settings.getValue('VSWITCH_BRIDGE_NAME')) diff --git a/core/vswitch_controller_pvvp.py b/core/vswitch_controller_pvvp.py index b445f9bd..43cf8a35 100644 --- a/core/vswitch_controller_pvvp.py +++ b/core/vswitch_controller_pvvp.py @@ -112,3 +112,8 @@ class VswitchControllerPVVP(IVswitchController): """ self._logger.debug('get_ports_info using ' + str(self._vswitch_class)) return self._vswitch.get_ports(settings.getValue('VSWITCH_BRIDGE_NAME')) + + def dump_vswitch_flows(self): + """See IVswitchController for description + """ + self._vswitch.dump_flows(settings.getValue('VSWITCH_BRIDGE_NAME')) diff --git a/docs/to-be-reorganized/NEWS.rst b/docs/to-be-reorganized/NEWS.rst index 69df7478..0fe9e22b 100644 --- a/docs/to-be-reorganized/NEWS.rst +++ b/docs/to-be-reorganized/NEWS.rst @@ -1,3 +1,9 @@ +October 2015 +============== +New +--- +- Support of PVP and PVVP deployment scenarios using Vanilla OVS + September 2015 ============== New @@ -63,4 +69,3 @@ Missing ------- - xmlunit output is currently disabled -- VNF support. diff --git a/docs/to-be-reorganized/quickstart.rst b/docs/to-be-reorganized/quickstart.rst index 485bf1ae..c575be59 100644 --- a/docs/to-be-reorganized/quickstart.rst +++ b/docs/to-be-reorganized/quickstart.rst @@ -203,7 +203,45 @@ To run tests using vhost-cuse as guest access method: ./vsperf --conf-file <path_to_settings_py> +Executing PVP tests using Vanilla OVS +------------------------------------- +To run tests using Vanilla OVS: + +1. Set the following variables: + + .. code-block:: console + + VSWITCH = 'OvsVanilla' + VNF = 'QemuVirtioNet' + + VANILLA_TGEN_PORT1_IP = n.n.n.n + VANILLA_TGEN_PORT1_MAC = nn:nn:nn:nn:nn:nn + + VANILLA_TGEN_PORT2_IP = n.n.n.n + VANILLA_TGEN_PORT2_MAC = nn:nn:nn:nn:nn:nn + + VANILLA_BRIDGE_IP = n.n.n.n + + or use --test-param + + ./vsperf --conf-file user_settings.py + --test-param "vanilla_tgen_tx_ip=n.n.n.n; + vanilla_tgen_tx_mac=nn:nn:nn:nn:nn:nn" + + +2. Recompile src for Vanilla OVS testing + .. code-block:: console + + cd src + make cleanse + make WITH_LINUX=/lib/modules/`uname -r`/build + +3. Run test: + + .. code-block:: console + + ./vsperf --conf-file <path_to_settings_py> GOTCHAs: -------- diff --git a/testcases/testcase.py b/testcases/testcase.py index e15572d8..feb264d3 100644 --- a/testcases/testcase.py +++ b/testcases/testcase.py @@ -23,7 +23,7 @@ from core.results.results_constants import ResultsConstants import core.component_factory as component_factory from core.loader import Loader from tools.report import report -from conf import settings +from conf import settings as S class TestCase(object): """TestCase base class @@ -92,12 +92,25 @@ class TestCase(object): 'bidir': self._bidir, 'multistream': self._multistream} + # OVS Vanilla requires guest VM MAC address and IPs + # to work + if (self.deployment in ["pvp", "pvvp"] and + S.getValue('VSWITCH') == "OvsVanilla"): + + traffic['l2'] = {'srcmac': S.getValue('GUEST_NET2_MAC')[0], + 'dstmac': S.getValue('GUEST_NET1_MAC')[0]} + + traffic['l3'] = {'srcip': + S.getValue('VANILLA_TGEN_PORT1_IP'), + 'dstip': + S.getValue('VANILLA_TGEN_PORT2_IP')} + vswitch = vswitch_ctl.get_vswitch() # TODO BOM 15-08-07 the frame mod code assumes that the # physical ports are ports 1 & 2. The actual numbers # need to be retrived from the vSwitch and the metadata value # updated accordingly. - bridge = settings.getValue('VSWITCH_BRIDGE_NAME') + bridge = S.getValue('VSWITCH_BRIDGE_NAME') if self._frame_mod == "vlan": # 0x8100 => VLAN ethertype self._logger.debug(" **** VLAN ***** ") @@ -178,6 +191,9 @@ class TestCase(object): with traffic_ctl: traffic_ctl.send_traffic(traffic) + # dump vswitch flows before they are affected by VNF termination + vswitch_ctl.dump_vswitch_flows() + self._logger.debug("Traffic Results:") traffic_ctl.print_results() diff --git a/tools/pkt_gen/ixnet/ixnetrfc2544.tcl b/tools/pkt_gen/ixnet/ixnetrfc2544.tcl index d5479b25..eda369db 100644 --- a/tools/pkt_gen/ixnet/ixnetrfc2544.tcl +++ b/tools/pkt_gen/ixnet/ixnetrfc2544.tcl @@ -702,7 +702,7 @@ proc startRfc2544Test { testSpec trafficSpec } { -frEncapsulation ::ixNet::OBJ-null \ -incrementPerVcVlanMode noIncrement \ -incrementVlanMode noIncrement \ - -mac "00:00:00:00:00:01" \ + -mac $srcMac \ -macRangeMode normal \ -numberOfVcs 1 \ -siteId 0 \ @@ -1082,7 +1082,7 @@ proc startRfc2544Test { testSpec trafficSpec } { -frEncapsulation ::ixNet::OBJ-null \ -incrementPerVcVlanMode noIncrement \ -incrementVlanMode noIncrement \ - -mac "00:01:00:05:08:00" \ + -mac $dstMac \ -macRangeMode normal \ -numberOfVcs 1 \ -siteId 0 \ @@ -2046,14 +2046,14 @@ proc startRfc2544Test { testSpec trafficSpec } { # set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.srcIp-27" ixNet setMultiAttrs $sg_field \ - -singleValue {1.1.1.1} \ + -singleValue $srcIp \ -seed {1} \ -optionalEnabled True \ -fullMesh False \ -valueList {{0.0.0.0}} \ -stepValue {0.0.0.0} \ -fixedBits {0.0.0.0} \ - -fieldValue {1.1.1.1} \ + -fieldValue $srcIp \ -auto False \ -randomMask {0.0.0.0} \ -trackingEnabled False \ @@ -2069,14 +2069,14 @@ proc startRfc2544Test { testSpec trafficSpec } { # set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.dstIp-28" ixNet setMultiAttrs $sg_field \ - -singleValue {90.90.90.90} \ + -singleValue $dstIp \ -seed {1} \ -optionalEnabled True \ -fullMesh False \ -valueList {{0.0.0.0}} \ -stepValue {0.0.0.0} \ -fixedBits {0.0.0.0} \ - -fieldValue {90.90.90.90} \ + -fieldValue $dstIp \ -auto False \ -randomMask {0.0.0.0} \ -trackingEnabled False \ @@ -3681,7 +3681,7 @@ proc startRfc2544Test { testSpec trafficSpec } { # set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.srcIp-27" ixNet setMultiAttrs $sg_field \ - -singleValue {1.1.1.1} \ + -singleValue $srcIp \ -seed {1} \ -optionalEnabled True \ -fullMesh False \ @@ -3704,14 +3704,14 @@ proc startRfc2544Test { testSpec trafficSpec } { # set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.dstIp-28" ixNet setMultiAttrs $sg_field \ - -singleValue {90.90.90.90} \ + -singleValue $dstIp \ -seed {1} \ -optionalEnabled True \ -fullMesh False \ -valueList {{0.0.0.0}} \ -stepValue {0.0.0.0} \ -fixedBits {0.0.0.0} \ - -fieldValue {90.90.90.90} \ + -fieldValue $dstIp \ -auto False \ -randomMask {0.0.0.0} \ -trackingEnabled False \ diff --git a/vnfs/qemu/qemu.py b/vnfs/qemu/qemu.py index 338ca771..2e2c63df 100644 --- a/vnfs/qemu/qemu.py +++ b/vnfs/qemu/qemu.py @@ -41,13 +41,7 @@ class IVnfQemu(IVnf): def __init__(self): """ - :param timeout: Time to wait for login prompt. If set to - 0 do not wait. - :param number: Number of QEMU instance, used when multiple QEMU - instances are started at once. - :param args: Arguments to pass to QEMU. - - :returns: None + Initialisation function. """ super(IVnfQemu, self).__init__() self._logger = logging.getLogger(__name__) @@ -67,9 +61,6 @@ class IVnfQemu(IVnf): '-cpu', 'host', '-drive', 'if=scsi,file=' + S.getValue('GUEST_IMAGE')[self._number], - '-drive', - 'if=scsi,file=fat:rw:%s,snapshot=off' % - S.getValue('GUEST_SHARE_DIR')[self._number], '-boot', 'c', '--enable-kvm', '-monitor', 'unix:%s,server,nowait' % self._monitor, '-object', @@ -104,7 +95,8 @@ class IVnfQemu(IVnf): Start QEMU instance, login and prepare for commands. """ super(IVnfQemu, self).start() - self._affinitize() + if S.getValue('VNF_AFFINITIZATION_ON'): + self._affinitize() if self._timeout: self._login() diff --git a/vnfs/qemu/qemu_dpdk.py b/vnfs/qemu/qemu_dpdk.py index 0b8f90a0..02d720f3 100644 --- a/vnfs/qemu/qemu_dpdk.py +++ b/vnfs/qemu/qemu_dpdk.py @@ -25,16 +25,13 @@ class IVnfQemuDpdk(IVnfQemu): def __init__(self): """ - :param timeout: Time to wait for login prompt. If set to - 0 do not wait. - :param number: Number of QEMU instance, used when multiple QEMU - instances are started at once. - :param args: Arguments to pass to QEMU. - - :returns: None + Initialisation function. """ super(IVnfQemuDpdk, self).__init__() - self._cmd += [] + self._cmd += ['-drive', + 'if=scsi,file=fat:rw:%s,snapshot=off' % + S.getValue('GUEST_SHARE_DIR')[self._number], + ] def _modify_dpdk_makefile(self): """ diff --git a/vnfs/qemu/qemu_virtio_net.py b/vnfs/qemu/qemu_virtio_net.py new file mode 100644 index 00000000..7de5ea1c --- /dev/null +++ b/vnfs/qemu/qemu_virtio_net.py @@ -0,0 +1,115 @@ +# Copyright 2016 Intel Corporation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Automation of QEMU hypervisor for launching virtio-net enabled guests. +""" + +import logging +from vnfs.qemu.qemu import IVnfQemu +from conf import settings as S +from conf import get_test_param +from tools import tasks + +class QemuVirtioNet(IVnfQemu): + """ + Control an instance of QEMU with virtio-net guest communication. + """ + + def __init__(self): + """ + Initialisation function. + """ + super(QemuVirtioNet, self).__init__() + self._logger = logging.getLogger(__name__) + + # insert vanilla ovs specific modules + tasks.run_task(['sudo', 'modprobe', 'vhost_net'], self._logger, + 'Loading vhost_net module...', True) + + # calculate indexes of guest devices (e.g. charx, dpdkvhostuserx) + i = self._number * 2 + if1 = str(i) + if2 = str(i + 1) + self._net1 = S.getValue('VANILLA_NIC1_NAME')[self._number] + self._net2 = S.getValue('VANILLA_NIC2_NAME')[self._number] + + self._cmd += ['-netdev', + 'type=tap,id=' + self._net1 + + ',script=no,downscript=no,' + + 'ifname=tap' + if1 + ',vhost=on', + '-device', + 'virtio-net-pci,mac=' + + S.getValue('GUEST_NET1_MAC')[self._number] + + ',netdev=' + self._net1 + ',csum=off,gso=off,' + + 'guest_tso4=off,guest_tso6=off,guest_ecn=off', + '-netdev', + 'type=tap,id=' + self._net2 + + ',script=no,downscript=no,' + + 'ifname=tap' + if2 + ',vhost=on', + '-device', + 'virtio-net-pci,mac=' + + S.getValue('GUEST_NET2_MAC')[self._number] + + ',netdev=' + self._net2 + ',csum=off,gso=off,' + + 'guest_tso4=off,guest_tso6=off,guest_ecn=off', + ] + + # helper functions + + def _config_guest_loopback(self): + """ + Configure VM to perform forwarding between NICs + """ + + # Disable services (F16) + self.execute_and_wait('systemctl stop iptables.service') + self.execute_and_wait('systemctl stop irqbalance.service') + + nic1_name = get_test_param('vanilla_nic1_name', self._net1) + self.execute('ifconfig ' + nic1_name + ' ' + + S.getValue('VANILLA_NIC1_IP_CIDR')[self._number]) + + nic2_name = get_test_param('vanilla_nic2_name', self._net2) + self.execute('ifconfig ' + nic2_name + ' ' + + S.getValue('VANILLA_NIC2_IP_CIDR')[self._number]) + + # configure linux bridge + self.execute('brctl addbr br0') + self.execute('brctl addif br0 ' + self._net1 + ' ' + self._net2) + self.execute('ifconfig br0 ' + + S.getValue('VANILLA_BRIDGE_IP')[self._number]) + + # Add the arp entries for the IXIA ports and the bridge you are using. + # Use command line values if provided. + trafficgen_mac = get_test_param('vanilla_tgen_port1_mac', + S.getValue('VANILLA_TGEN_PORT1_MAC')) + trafficgen_ip = get_test_param('vanilla_tgen_port1_ip', + S.getValue('VANILLA_TGEN_PORT1_IP')) + + self.execute('arp -s ' + trafficgen_ip + ' ' + trafficgen_mac) + + trafficgen_mac = get_test_param('vanilla_tgen_port2_mac', + S.getValue('VANILLA_TGEN_PORT2_MAC')) + trafficgen_ip = get_test_param('vanilla_tgen_port2_ip', + S.getValue('VANILLA_TGEN_PORT2_IP')) + + self.execute('arp -s ' + trafficgen_ip + ' ' + trafficgen_mac) + + # Enable forwarding + self.execute('sysctl -w net.ipv4.ip_forward=1') + + # Controls source route verification + # 0 means no source validation + self.execute('sysctl -w net.ipv4.conf.all.rp_filter=0') + self.execute('sysctl -w net.ipv4.conf.' + self._net1 + '.rp_filter=0') + self.execute('sysctl -w net.ipv4.conf.' + self._net2 + '.rp_filter=0') diff --git a/vnfs/vnf/vnf.py b/vnfs/vnf/vnf.py index f8d2df90..483faf38 100644 --- a/vnfs/vnf/vnf.py +++ b/vnfs/vnf/vnf.py @@ -121,3 +121,13 @@ class IVnf(tasks.Process): """ self.execute(cmd) self.wait(prompt=prompt, timeout=timeout) + + @staticmethod + def reset_vnf_counter(): + """ + Reset internal VNF counters + + This method is static + """ + IVnf._number_vnfs = 0 + diff --git a/vswitches/ovs_dpdk_vhost.py b/vswitches/ovs_dpdk_vhost.py index 1a53bd6d..874cc97b 100644 --- a/vswitches/ovs_dpdk_vhost.py +++ b/vswitches/ovs_dpdk_vhost.py @@ -158,6 +158,12 @@ class OvsDpdkVhost(IVSwitch): bridge = self._bridges[switch_name] bridge.del_flow(flow) + def dump_flows(self, switch_name): + """See IVswitch for general description + """ + bridge = self._bridges[switch_name] + bridge.dump_flows() + @staticmethod def _get_port_count(bridge, param): """Returns the number of ports having a certain parameter diff --git a/vswitches/ovs_vanilla.py b/vswitches/ovs_vanilla.py index a7d4d206..6716401d 100644 --- a/vswitches/ovs_vanilla.py +++ b/vswitches/ovs_vanilla.py @@ -20,7 +20,9 @@ from conf import settings from vswitches.vswitch import IVSwitch from src.ovs import VSwitchd, OFBridge from tools.module_manager import ModuleManager, KernelModuleInsertMode +from tools import tasks +_LOGGER = logging.getLogger(__name__) VSWITCHD_CONST_ARGS = ['--', '--log-file'] class OvsVanilla(IVSwitch): @@ -36,6 +38,7 @@ class OvsVanilla(IVSwitch): _logger = logging.getLogger() _ports = settings.getValue('VSWITCH_VANILLA_PHY_PORT_NAMES') _current_id = 0 + _vport_id = 0 def __init__(self): #vswitchd_args = VSWITCHD_CONST_ARGS @@ -62,9 +65,18 @@ class OvsVanilla(IVSwitch): Kills ovsdb and vswitchd and removes kernel modules. """ + # remove all tap interfaces + for i in range(self._vport_id): + tapx = 'tap' + str(i) + tasks.run_task(['sudo', 'ip', 'tuntap', 'del', + tapx, 'mode', 'tap'], + _LOGGER, 'Deleting ' + tapx, False) + self._vport_id = 0 + self._vswitchd.kill() self._module_manager.remove_modules() + def add_switch(self, switch_name): """See IVswitch for general description """ @@ -94,16 +106,47 @@ class OvsVanilla(IVSwitch): "defined in config!") raise + if not self._ports[self._current_id]: + self._logger.error("VSWITCH_VANILLA_PHY_PORT_NAMES not set") + raise ValueError("Invalid VSWITCH_VANILLA_PHY_PORT_NAMES") + bridge = self._bridges[switch_name] port_name = self._ports[self._current_id] params = [] + + # For PVP only + tasks.run_task(['sudo', 'ifconfig', port_name, '0'], + _LOGGER, 'Remove IP', False) + of_port = bridge.add_port(port_name, params) self._current_id += 1 return (port_name, of_port) def add_vport(self, switch_name): - """See IVswitch for general description""" - raise NotImplementedError("Not implemented for Vanilla OVS.") + """ + Method adds virtual port into OVS vanilla + + See IVswitch for general description + """ + # Create tap devices for the VM + tap_name = 'tap' + str(self._vport_id) + self._vport_id += 1 + + tasks.run_task(['sudo', 'ip', 'tuntap', 'del', + tap_name, 'mode', 'tap'], + _LOGGER, 'Creating tap device...', False) + + tasks.run_task(['sudo', 'ip', 'tuntap', 'add', + tap_name, 'mode', 'tap'], + _LOGGER, 'Creating tap device...', False) + + tasks.run_task(['sudo', 'ifconfig', tap_name, '0'], + _LOGGER, 'Bring up ' + tap_name, False) + + bridge = self._bridges[switch_name] + of_port = bridge.add_port(tap_name, []) + return (tap_name, of_port) + def get_ports(self, switch_name): """See IVswitch for general description @@ -130,3 +173,9 @@ class OvsVanilla(IVSwitch): flow = flow or {} bridge = self._bridges[switch_name] bridge.del_flow(flow) + + def dump_flows(self, switch_name): + """See IVswitch for general description + """ + bridge = self._bridges[switch_name] + bridge.dump_flows() diff --git a/vswitches/vswitch.py b/vswitches/vswitch.py index 713974ae..dbf3e7d5 100644 --- a/vswitches/vswitch.py +++ b/vswitches/vswitch.py @@ -112,3 +112,10 @@ class IVSwitch(object): For flow==None, all flows are deleted """ raise NotImplementedError() + + def dump_flows(self, switch_name): + """Dump flows from the logical switch + + :param switch_name: The switch on which to operate + """ + raise NotImplementedError() |