diff options
-rw-r--r-- | conf/integration/01_testcases.conf | 49 | ||||
-rw-r--r-- | conf/integration/02_vswitch.conf | 24 | ||||
-rw-r--r-- | conf/integration/03_traffic.conf | 20 | ||||
-rw-r--r-- | core/component_factory.py | 7 | ||||
-rw-r--r-- | core/vnf_controller.py | 6 | ||||
-rw-r--r-- | core/vswitch_controller_op2p.py | 140 | ||||
-rw-r--r-- | docs/configguide/index.rst | 1 | ||||
-rw-r--r-- | docs/userguide/index.rst | 1 | ||||
-rwxr-xr-x | docs/userguide/integration.rst | 97 | ||||
-rw-r--r-- | src/ovs/ofctl.py | 50 | ||||
-rw-r--r-- | testcases/testcase.py | 19 | ||||
-rwxr-xr-x | vsperf | 8 | ||||
-rw-r--r-- | vswitches/ovs_dpdk_vhost.py | 50 | ||||
-rw-r--r-- | vswitches/ovs_vanilla.py | 49 | ||||
-rw-r--r-- | vswitches/vswitch.py | 28 |
15 files changed, 528 insertions, 21 deletions
diff --git a/conf/integration/01_testcases.conf b/conf/integration/01_testcases.conf new file mode 100644 index 00000000..99154ad3 --- /dev/null +++ b/conf/integration/01_testcases.conf @@ -0,0 +1,49 @@ +# Copyright 2015-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. + +# The 1st value of SUPPORTED_TUNNELING_PROTO is used as the default +# tunneling protocol for OP2P tests. +SUPPORTED_TUNNELING_PROTO = ['vxlan', 'gre', 'geneve'] + +# Required for OP2P tests +# "Tunnel Type": ["vxlan"|"gre"|"geneve"] # Tunnel Type defines tunneling protocol to use. +# # It can be overridden by cli option tunnel_type. +# # Values: +# # "vxlan" - iteration of destination MAC address +# # "gre" - iteration of destination IP address +# # "geneve" - iteration of destination UDP port +# # Default value is "vxlan". +# +# biDirectional testing for OP2P is not yet supported. +# biDirectional must be set to False. + +INTEGRATION_TESTS = [ + { + "Name": "overlay_p2p_tput", + "Traffic Type": "rfc2544", + "Deployment": "op2p", + "biDirectional": False, + "Tunnel Type": SUPPORTED_TUNNELING_PROTO[0], + "Description": "Overlay Encapsulation Throughput RFC2544 Test", + }, + { + "Name": "overlay_p2p_cont", + "Traffic Type": "continuous", + "Deployment": "op2p", + "biDirectional": False, + "Tunnel Type": SUPPORTED_TUNNELING_PROTO[0], + "Description": "Overlay Encapsulation Continuous Stream", + }, +] + diff --git a/conf/integration/02_vswitch.conf b/conf/integration/02_vswitch.conf new file mode 100644 index 00000000..20cec3e6 --- /dev/null +++ b/conf/integration/02_vswitch.conf @@ -0,0 +1,24 @@ +# Copyright 2015-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. + +# Tunnel endpoint for Overlay P2P deployment scenario +VTEP_IP1 = '192.168.0.1/24' +VTEP_IP2 = '192.168.240.10' +VTEP_IP2_SUBNET = '192.168.240.0/24' +TUNNEL_INTEGRATION_BRIDGE = 'br0' +TUNNEL_EXTERNAL_BRIDGE = 'br-ext' +TUNNEL_EXTERNAL_BRIDGE_IP = '192.168.240.1/24' + +# vxlan|gre|geneve +TUNNEL_TYPE = 'vxlan' diff --git a/conf/integration/03_traffic.conf b/conf/integration/03_traffic.conf new file mode 100644 index 00000000..8bef092a --- /dev/null +++ b/conf/integration/03_traffic.conf @@ -0,0 +1,20 @@ +# Copyright 2015-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. + +# For OP2P deployment scenario +TRAFFICGEN_PORT1_MAC = '02:00:00:00:00:01' +TRAFFICGEN_PORT2_MAC = '02:00:00:00:00:02' +TRAFFICGEN_PORT1_IP = '1.1.1.1' +TRAFFICGEN_PORT2_IP = '90.90.90.90' + diff --git a/core/component_factory.py b/core/component_factory.py index af237e50..1e5f2266 100644 --- a/core/component_factory.py +++ b/core/component_factory.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-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. @@ -19,6 +19,7 @@ from core.traffic_controller_rfc2544 import TrafficControllerRFC2544 from core.vswitch_controller_p2p import VswitchControllerP2P from core.vswitch_controller_pvp import VswitchControllerPVP from core.vswitch_controller_pvvp import VswitchControllerPVVP +from core.vswitch_controller_op2p import VswitchControllerOP2P from core.vnf_controller import VnfController from core.pktfwd_controller import PktFwdController from tools.load_gen.stress.stress import Stress @@ -61,12 +62,14 @@ def create_vswitch(deployment_scenario, vswitch_class, traffic): :return: IVSwitchController for the deployment_scenario """ deployment_scenario = deployment_scenario.lower() - if deployment_scenario.find("p2p") >= 0: + if deployment_scenario.find("p2p") == 0: return VswitchControllerP2P(vswitch_class, traffic) elif deployment_scenario.find("pvp") >= 0: return VswitchControllerPVP(vswitch_class, traffic) elif deployment_scenario.find("pvvp") >= 0: return VswitchControllerPVVP(vswitch_class, traffic) + elif deployment_scenario.find("op2p") >= 0: + return VswitchControllerOP2P(vswitch_class, traffic) def create_vnf(deployment_scenario, vnf_class): """Return a new VnfController for the deployment_scenario. diff --git a/core/vnf_controller.py b/core/vnf_controller.py index 3313e9e3..e973bc51 100644 --- a/core/vnf_controller.py +++ b/core/vnf_controller.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-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. @@ -43,10 +43,12 @@ class VnfController(object): self._deployment_scenario = deployment_scenario.upper() if self._deployment_scenario == 'P2P': self._vnfs = [] - if self._deployment_scenario == 'PVP': + elif self._deployment_scenario == 'PVP': self._vnfs = [vnf_class()] elif self._deployment_scenario == 'PVVP': self._vnfs = [vnf_class(), vnf_class()] + elif self._deployment_scenario == 'OP2P': + self._vnfs = [] self._logger.debug('__init__ ' + str(len(self._vnfs)) + ' VNF[s] with ' + ' '.join(map(str, self._vnfs))) diff --git a/core/vswitch_controller_op2p.py b/core/vswitch_controller_op2p.py new file mode 100644 index 00000000..69c88c35 --- /dev/null +++ b/core/vswitch_controller_op2p.py @@ -0,0 +1,140 @@ +# Copyright 2015-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. + +"""VSwitch controller for Physical to Tunnel Endpoint to Physical deployment +""" + +import logging + +from core.vswitch_controller import IVswitchController +from vswitches.utils import add_ports_to_flow +from conf import settings +from tools import tasks + +_FLOW_TEMPLATE = { + 'idle_timeout': '0' +} + +class VswitchControllerOP2P(IVswitchController): + """VSwitch controller for OP2P deployment scenario. + + Attributes: + _vswitch_class: The vSwitch class to be used. + _vswitch: The vSwitch object controlled by this controller + _deployment_scenario: A string describing the scenario to set-up in the + constructor. + """ + def __init__(self, vswitch_class, traffic): + """Initializes up the prerequisites for the OP2P deployment scenario. + + :vswitch_class: the vSwitch class to be used. + """ + self._logger = logging.getLogger(__name__) + self._vswitch_class = vswitch_class + self._vswitch = vswitch_class() + self._deployment_scenario = "OP2P" + self._traffic = traffic.copy() + self._logger.debug('Creation using ' + str(self._vswitch_class)) + + def setup(self): + """ Sets up the switch for overlay P2P + + Create 2 bridges br0 (integration bridge) and br-ext and a VXLAN port + for encapsulation. + """ + self._logger.debug('Setup using ' + str(self._vswitch_class)) + + try: + self._vswitch.start() + bridge = settings.getValue('TUNNEL_INTEGRATION_BRIDGE') + bridge_ext = settings.getValue('TUNNEL_EXTERNAL_BRIDGE') + bridge_ext_ip = settings.getValue('TUNNEL_EXTERNAL_BRIDGE_IP') + tg_port2_mac = settings.getValue('TRAFFICGEN_PORT2_MAC') + vtep_ip2 = settings.getValue('VTEP_IP2') + self._vswitch.add_switch(bridge) + + tasks.run_task(['sudo', 'ifconfig', bridge, + settings.getValue('VTEP_IP1')], + self._logger, 'Assign ' + + settings.getValue('VTEP_IP1') + ' to ' + bridge, + False) + + tunnel_type = self._traffic['tunnel_type'] + + self._vswitch.add_switch(bridge_ext) + (_, phy1_number) = self._vswitch.add_phy_port(bridge) + (_, phy2_number) = self._vswitch.add_tunnel_port(bridge, + vtep_ip2, + tunnel_type) + self._vswitch.add_phy_port(bridge_ext) + + tasks.run_task(['sudo', 'ip', 'addr', 'add', + bridge_ext_ip, + 'dev', bridge_ext], self._logger, 'Assign ' + + bridge_ext_ip + ' to ' + bridge_ext) + + tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', bridge_ext, + 'up'], self._logger, + 'Set ' + bridge_ext + 'status to up') + + self._vswitch.add_route(bridge, + settings.getValue('VTEP_IP2_SUBNET'), + bridge_ext) + + if settings.getValue('VSWITCH').endswith('Vanilla'): + tasks.run_task(['sudo', 'arp', '-s', vtep_ip2, tg_port2_mac], + self._logger, + 'Set ' + bridge_ext + 'status to up') + else: + self._vswitch.set_tunnel_arp(vtep_ip2, + tg_port2_mac, + bridge_ext) + + # Test is unidirectional for now + self._vswitch.del_flow(bridge) + flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number, + phy2_number) + self._vswitch.add_flow(bridge, flow1) + + except: + self._vswitch.stop() + raise + + def stop(self): + """Tears down the switch created in setup(). + """ + self._logger.debug('Stop using ' + str(self._vswitch_class)) + self._vswitch.stop() + + def __enter__(self): + self.setup() + + def __exit__(self, type_, value, traceback): + self.stop() + + def get_vswitch(self): + """See IVswitchController for description + """ + return self._vswitch + + def get_ports_info(self): + """See IVswitchController for description + """ + 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/configguide/index.rst b/docs/configguide/index.rst index 3aaf238f..7ea39cd1 100644 --- a/docs/configguide/index.rst +++ b/docs/configguide/index.rst @@ -8,3 +8,4 @@ VSPERF Installation Guide installation.rst trafficgen.rst + integration.rst diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst index 1e02eb21..ff4e7b52 100644 --- a/docs/userguide/index.rst +++ b/docs/userguide/index.rst @@ -7,3 +7,4 @@ VSPERF User Guide :maxdepth: 3 quickstart.rst + integration.rst diff --git a/docs/userguide/integration.rst b/docs/userguide/integration.rst new file mode 100755 index 00000000..65b86468 --- /dev/null +++ b/docs/userguide/integration.rst @@ -0,0 +1,97 @@ +Integration tests +================= + +VSPERF includes a set of integration tests defined in conf/integration. +These tests can be run by specifying --run-integration as a parameter to vsperf. +Current tests in conf/integration are Overlay tests. + + +Executing Tunnel encapsulation tests +------------------------------------ + +VSPERF supports VXLAN, GRE and GENEVE tunneling protocols. +Testing of these protocols is limited to unidirectional traffic and +P2P (Physical to Physical scenarios). + +The VXLAN OVS DPDK encapsulation tests requires IPs, MAC addresses, +bridge names and WHITELIST_NICS for DPDK. + +Default values are already provided. To customize for your environment, override +the following variables in you user_settings.py file: + +# Variables defined in conf/integration/02_vswitch.conf +# Tunnel endpoint for Overlay P2P deployment scenario +# used for br0 +VTEP_IP1 = '192.168.0.1/24' + +# Used as remote_ip in adding OVS tunnel port and +# to set ARP entry in OVS (e.g. tnl/arp/set br-ext 192.168.240.10 02:00:00:00:00:02 +VTEP_IP2 = '192.168.240.10' + +# Network to use when adding a route for inner frame data +VTEP_IP2_SUBNET = '192.168.240.0/24' + +# Bridge names +TUNNEL_INTEGRATION_BRIDGE = 'br0' +TUNNEL_EXTERNAL_BRIDGE = 'br-ext' + +# IP of br-ext +TUNNEL_EXTERNAL_BRIDGE_IP = '192.168.240.1/24' + +# vxlan|gre|geneve +TUNNEL_TYPE = 'vxlan' + +# Variables defined conf/integration/03_traffic.conf +# For OP2P deployment scenario +TRAFFICGEN_PORT1_MAC = '02:00:00:00:00:01' +TRAFFICGEN_PORT2_MAC = '02:00:00:00:00:02' +TRAFFICGEN_PORT1_IP = '1.1.1.1' +TRAFFICGEN_PORT2_IP = '192.168.240.10' + + +To run VXLAN encapsulation tests: + + .. code-block:: console + + ./vsperf --conf-file user_settings.py --run-integration --test-param 'tunnel_type=vxlan' overlay_p2p_tput + +To run GRE encapsulation tests: + + .. code-block:: console + + ./vsperf --conf-file user_settings.py --run-integration --test-param 'tunnel_type=gre' overlay_p2p_tput + +To run GENEVE encapsulation tests: + + .. code-block:: console + + ./vsperf --conf-file user_settings.py --run-integration --test-param 'tunnel_type=geneve' overlay_p2p_tput + +To run OVS NATIVE tunnel tests (VXLAN/GRE/GENEVE): + +1. Install the OVS kernel modules + + .. code:: console + + cd src/ovs/ovs + sudo -E make modules_install + +2. Set the following variables: + + .. code-block:: console + + VSWITCH = 'OvsVanilla' + VSWITCH_VANILLA_PHY_PORT_NAMES = ['nic1name', 'nic2name'] + # Specify vport_* kernel module to test. + VSWITCH_VANILLA_KERNEL_MODULES = ['vport_vxlan', + 'vport_gre', + 'vport_geneve', + os.path.join(OVS_DIR_VANILLA, 'datapath/linux/openvswitch.ko')] + +3. Run tests: + + .. code-block:: console + + ./vsperf --conf-file user_settings.py --run-integration --test-param 'tunnel_type=vxlan' overlay_p2p_tput + + diff --git a/src/ovs/ofctl.py b/src/ovs/ofctl.py index 9d16ef76..43151d3a 100644 --- a/src/ovs/ofctl.py +++ b/src/ovs/ofctl.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-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. @@ -31,6 +31,8 @@ _OVS_VSCTL_BIN = os.path.join(settings.getValue('OVS_DIR'), 'utilities', 'ovs-vsctl') _OVS_OFCTL_BIN = os.path.join(settings.getValue('OVS_DIR'), 'utilities', 'ovs-ofctl') +_OVS_APPCTL_BIN = os.path.join(settings.getValue('OVS_DIR'), 'utilities', + 'ovs-appctl') _OVS_BRIDGE_NAME = settings.getValue('VSWITCH_BRIDGE_NAME') @@ -63,6 +65,22 @@ class OFBase(object): return tasks.run_task( cmd, self.logger, 'Running ovs-vsctl...', check_error) + + def run_appctl(self, args, check_error=False): + """Run ``ovs-appctl`` with supplied arguments. + + :param args: Arguments to pass to ``ovs-appctl`` + :param check_error: Throw exception on error + + :return: None + """ + cmd = ['sudo', _OVS_APPCTL_BIN, + '--timeout', + str(self.timeout)] + args + return tasks.run_task( + cmd, self.logger, 'Running ovs-appctl...', check_error) + + # datapath management def add_br(self, br_name=_OVS_BRIDGE_NAME, params=None): @@ -90,6 +108,32 @@ class OFBase(object): self.logger.debug('delete bridge') self.run_vsctl(['del-br', br_name]) + # Route and ARP functions + + def add_route(self, network, destination): + """Add route to tunneling routing table. + + :param network: Network + :param destination: Gateway + + :return: None + """ + self.logger.debug('add ovs/route') + self.run_appctl(['ovs/route/add', network, destination]) + + + def set_tunnel_arp(self, ip_addr, mac_addr, br_name=_OVS_BRIDGE_NAME): + """Add OVS arp entry for tunneling + + :param ip: IP of bridge + :param mac_addr: MAC address of the bridge + :param br_name: Name of the bridge + + :return: None + """ + self.logger.debug('tnl/arp/set') + self.run_appctl(['tnl/arp/set', br_name, ip_addr, mac_addr]) + class OFBridge(OFBase): """Control a bridge instance using ``ovs-vsctl`` and ``ovs-ofctl``. @@ -330,10 +374,10 @@ def flow_key(flow): field_params.append('%(field)s=%(value)s' % {'field': key, 'value': default}) - field_params = ','.join(field_params) + field_params_str = ','.join(field_params) _flow_key_param = { - 'fields': field_params, + 'fields': field_params_str, } # no actions == delete key diff --git a/testcases/testcase.py b/testcases/testcase.py index d470d951..945b8537 100644 --- a/testcases/testcase.py +++ b/testcases/testcase.py @@ -28,8 +28,8 @@ from core.loader import Loader from tools import tasks from tools import hugepages from tools.report import report -from conf import settings as S from tools.pkt_gen.trafficgen.trafficgenhelper import TRAFFIC_DEFAULTS +from conf import settings as S from conf import get_test_param class TestCase(object): @@ -64,6 +64,11 @@ class TestCase(object): self.deployment = cfg['Deployment'] self._frame_mod = cfg.get('Frame Modification', None) + tunnel_type = None + if 'Tunnel Type' in cfg: + tunnel_type = cfg['Tunnel Type'] + tunnel_type = get_test_param('tunnel_type', tunnel_type) + # identify guest loopback method, so it can be added into reports self.guest_loopback = [] if self.deployment in ['pvp', 'pvvp']: @@ -102,6 +107,7 @@ class TestCase(object): self._traffic.update({'traffic_type': traffic_type, 'flow_type': cfg.get('Flow Type', 'port'), 'bidir': bidirectional, + 'tunnel_type': tunnel_type, 'multistream': int(multistream), 'stream_type': stream_type, 'pre_installed_flows' : pre_installed_flows, @@ -130,6 +136,17 @@ class TestCase(object): # copy sources of l2 forwarding tools into VM shared dir if needed self._copy_fwd_tools_for_guest() + if self.deployment == "op2p": + self._traffic['l2'].update({'srcmac': + S.getValue('TRAFFICGEN_PORT1_MAC'), + 'dstmac': + S.getValue('TRAFFICGEN_PORT2_MAC')}) + + self._traffic['l3'].update({'srcip': + S.getValue('TRAFFICGEN_PORT1_IP'), + 'dstip': + S.getValue('TRAFFICGEN_PORT2_IP')}) + self._logger.debug("Controllers:") loader = Loader() traffic_ctl = component_factory.create_traffic( @@ -154,6 +154,7 @@ def parse_arguments(): name contains RFC2544 less those containing "p2p"') group.add_argument('--verbosity', choices=list_logging_levels(), help='debug level') + group.add_argument('--run-integration', action='store_true', help='run integration tests') group.add_argument('--trafficgen', help='traffic generator to use') group.add_argument('--vswitch', help='vswitch implementation to use') group.add_argument('--fwdapp', help='packet forwarding application to use') @@ -325,6 +326,10 @@ def main(): settings.load_from_dir('conf') + # Load non performance/integration tests + if args['run_integration']: + settings.load_from_dir('conf/integration') + # load command line parameters first in case there are settings files # to be used settings.load_from_dict(args) @@ -455,6 +460,9 @@ def main(): else: # configure tests testcases = settings.getValue('PERFORMANCE_TESTS') + if args['run_integration']: + testcases = settings.getValue('INTEGRATION_TESTS') + all_tests = [] for cfg in testcases: try: diff --git a/vswitches/ovs_dpdk_vhost.py b/vswitches/ovs_dpdk_vhost.py index 2c7b81ff..074e15f8 100644 --- a/vswitches/ovs_dpdk_vhost.py +++ b/vswitches/ovs_dpdk_vhost.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-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. @@ -21,7 +21,7 @@ from vswitches.vswitch import IVSwitch from src.ovs import VSwitchd, OFBridge from src.dpdk import dpdk -_VSWITCHD_CONST_ARGS = ['--', '--log-file'] +_VSWITCHD_CONST_ARGS = ['--', '--pidfile', '--log-file'] class OvsDpdkVhost(IVSwitch): """VSwitch implementation using DPDK and vhost ports @@ -77,7 +77,7 @@ class OvsDpdkVhost(IVSwitch): 'datapath_type=netdev']) else: bridge.create(['--', 'set', 'bridge', switch_name, - 'datapath_type=netdev'] + params) + 'datapath_type=netdev'] + params) bridge.set_db_attribute('Open_vSwitch', '.', 'other_config:max-idle', @@ -106,7 +106,7 @@ class OvsDpdkVhost(IVSwitch): The new port is named dpdk<n> where n is an integer starting from 0. """ bridge = self._bridges[switch_name] - dpdk_count = self._get_port_count(bridge, 'type=dpdk') + dpdk_count = self._get_port_count('type=dpdk') port_name = 'dpdk' + str(dpdk_count) params = ['--', 'set', 'Interface', port_name, 'type=dpdk'] of_port = bridge.add_port(port_name, params) @@ -123,11 +123,11 @@ class OvsDpdkVhost(IVSwitch): bridge = self._bridges[switch_name] # Changed dpdkvhost to dpdkvhostuser to be able to run in Qemu 2.2 if settings.getValue('VNF').endswith('Cuse'): - vhost_count = self._get_port_count(bridge, 'type=dpdkvhostcuse') + vhost_count = self._get_port_count('type=dpdkvhostcuse') port_name = 'dpdkvhostcuse' + str(vhost_count) params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostcuse'] else: - vhost_count = self._get_port_count(bridge, 'type=dpdkvhostuser') + vhost_count = self._get_port_count('type=dpdkvhostuser') port_name = 'dpdkvhostuser' + str(vhost_count) params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser'] @@ -135,6 +135,17 @@ class OvsDpdkVhost(IVSwitch): return (port_name, of_port) + def add_tunnel_port(self, switch_name, remote_ip, tunnel_type='vxlan'): + """Creates tunneling port + """ + bridge = self._bridges[switch_name] + pcount = str(self._get_port_count('type=' + tunnel_type)) + port_name = tunnel_type + pcount + params = ['--', 'set', 'Interface', port_name, 'type=' + tunnel_type, + 'options:remote_ip=' + remote_ip] + of_port = bridge.add_port(port_name, params) + return (port_name, of_port) + def get_ports(self, switch_name): """See IVswitch for general description """ @@ -167,14 +178,31 @@ class OvsDpdkVhost(IVSwitch): bridge = self._bridges[switch_name] bridge.dump_flows() - @staticmethod - def _get_port_count(bridge, param): + def add_route(self, switch_name, network, destination): + """See IVswitch for general description + """ + bridge = self._bridges[switch_name] + bridge.add_route(network, destination) + + def set_tunnel_arp(self, ip_addr, mac_addr, switch_name): + """See IVswitch for general description + """ + bridge = self._bridges[switch_name] + bridge.set_tunnel_arp(ip_addr, mac_addr, switch_name) + + def _get_port_count(self, param): """Returns the number of ports having a certain parameter :param bridge: The src.ovs.ofctl.OFBridge on which to operate :param param: The parameter to search for :returns: Count of matches """ - port_params = [c for (_, (_, c)) in list(bridge.get_ports().items())] - param_hits = [i for i in port_params if param in i] - return len(param_hits) + cnt = 0 + for k in self._bridges: + pparams = [c for (_, (_, c)) in list(self._bridges[k].get_ports().items())] + phits = [i for i in pparams if param in i] + cnt += len(phits) + + if cnt is None: + cnt = 0 + return cnt diff --git a/vswitches/ovs_vanilla.py b/vswitches/ovs_vanilla.py index 3078de02..77d3deaf 100644 --- a/vswitches/ovs_vanilla.py +++ b/vswitches/ovs_vanilla.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-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. @@ -150,6 +150,22 @@ class OvsVanilla(IVSwitch): of_port = bridge.add_port(tap_name, []) return (tap_name, of_port) + def add_tunnel_port(self, switch_name, remote_ip, tunnel_type='vxlan', + params=None): + """Creates tunneling port + """ + bridge = self._bridges[switch_name] + pcount = str(self._get_port_count('type=' + tunnel_type)) + port_name = tunnel_type + pcount + local_params = ['--', 'set', 'Interface', port_name, + 'type=' + tunnel_type, + 'options:remote_ip=' + remote_ip] + + if params is not None: + local_params = local_params + params + + of_port = bridge.add_port(port_name, local_params) + return (port_name, of_port) def get_ports(self, switch_name): """See IVswitch for general description @@ -182,3 +198,34 @@ class OvsVanilla(IVSwitch): """ bridge = self._bridges[switch_name] bridge.dump_flows() + + def add_route(self, switch_name, network, destination): + """See IVswitch for general description + """ + bridge = self._bridges[switch_name] + bridge.add_route(network, destination) + + def set_tunnel_arp(self, ip_addr, mac_addr, switch_name): + """See IVswitch for general description + """ + bridge = self._bridges[switch_name] + bridge.set_tunnel_arp(ip_addr, mac_addr, switch_name) + + def _get_port_count(self, param): + """Returns the number of ports having a certain parameter + + :param bridge: The src.ovs.ofctl.OFBridge on which to operate + :param param: The parameter to search for + :returns: Count of matches + """ + cnt = 0 + for k in self._bridges: + pparams = [c for (_, (_, c)) in list(self._bridges[k].get_ports().items())] + phits = [i for i in pparams if param in i] + cnt += len(phits) + + if cnt is None: + cnt = 0 + return cnt + + diff --git a/vswitches/vswitch.py b/vswitches/vswitch.py index a28c0f6b..73e0a0c3 100644 --- a/vswitches/vswitch.py +++ b/vswitches/vswitch.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-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. @@ -71,6 +71,14 @@ class IVSwitch(object): """ raise NotImplementedError() + def add_tunnel_port(self, switch_name, remote_ip, tunnel_type, params=None): + """Create a new port to the logical switch for tunneling + + :param switch_name: The switch where the port is attached to + :returns: (port name, OpenFlow port number) + """ + raise NotImplementedError() + def get_ports(self, switch_name): """Return a list of tuples describing the ports of the logical switch @@ -128,3 +136,21 @@ class IVSwitch(object): :param switch_name: The switch on which to operate """ raise NotImplementedError() + + def add_route(self, switch_name, network, destination): + """Add a route for tunneling routing table + + :param switch_name: The switch on which to operate + :param network: Target destination network + :param destination: Gateway IP + """ + raise NotImplementedError() + + def set_tunnel_arp(self, ip_addr, mac_addr, switch_name): + """Add arp entry for tunneling + + :param ip_addr: IP of bridge + :param mac_addr: MAC address of the bridge + :param switch_name: Name of the bridge + """ + raise NotImplementedError() |