Add OVS tunnel encapsulation performance test 53/6553/9
authorDino Simeon Madarang <dino.simeonx.madarang@intel.com>
Mon, 19 Oct 2015 13:55:06 +0000 (14:55 +0100)
committerMaryam Tahhan <maryam.tahhan@intel.com>
Wed, 3 Feb 2016 10:17:04 +0000 (10:17 +0000)
Measure OVS DPDK and native VXLAN/GRE/GENEVE encapsulation performance.
This patch creates a new deployment scenario, Overlay_P2P.
The DUT is configured as a TEP (Tunnel Endpoint)
which performs encapsulation of frames and sends traffic to
the 2nd traffic generator port. The traffic generator in this
case receives an encapsulated frame. No decapsulation is performed
in this testcase.

Introduce a vsperf param, --run-integration, to filter tests to
integration tests. When running integration tests, variables defined
in the directory conf/integration/*conf as well as the conf/*.conf
are available.

This test case requires DPDK 2.1.0 and OVS master - 6bb4a18 or newer.

Change-Id: Ide2f418909d647119388df9b30d0d0a3656b4e53
JIRA: VSPERF-180
Signed-off-by: Dino Simeon Madarang <dino.simeonx.madarang@intel.com>
Reviewed-by: Maryam Tahhan <maryam.tahhan@intel.com>
Reviewed-by: Al Morton <acmorton@att.com>
15 files changed:
conf/integration/01_testcases.conf [new file with mode: 0644]
conf/integration/02_vswitch.conf [new file with mode: 0644]
conf/integration/03_traffic.conf [new file with mode: 0644]
core/component_factory.py
core/vnf_controller.py
core/vswitch_controller_op2p.py [new file with mode: 0644]
docs/configguide/index.rst
docs/userguide/index.rst
docs/userguide/integration.rst [new file with mode: 0755]
src/ovs/ofctl.py
testcases/testcase.py
vsperf
vswitches/ovs_dpdk_vhost.py
vswitches/ovs_vanilla.py
vswitches/vswitch.py

diff --git a/conf/integration/01_testcases.conf b/conf/integration/01_testcases.conf
new file mode 100644 (file)
index 0000000..99154ad
--- /dev/null
@@ -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 (file)
index 0000000..20cec3e
--- /dev/null
@@ -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 (file)
index 0000000..8bef092
--- /dev/null
@@ -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'
+
index af237e5..1e5f226 100644 (file)
@@ -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.
index 3313e9e..e973bc5 100644 (file)
@@ -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 (file)
index 0000000..69c88c3
--- /dev/null
@@ -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'))
index 3aaf238..7ea39cd 100644 (file)
@@ -8,3 +8,4 @@ VSPERF Installation Guide
 
    installation.rst
    trafficgen.rst
+   integration.rst
index 1e02eb2..ff4e7b5 100644 (file)
@@ -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 (executable)
index 0000000..65b8646
--- /dev/null
@@ -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
+
+
index 9d16ef7..43151d3 100644 (file)
@@ -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
index d470d95..945b853 100644 (file)
@@ -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(
diff --git a/vsperf b/vsperf
index 4b1d86d..71ca2eb 100755 (executable)
--- a/vsperf
+++ b/vsperf
@@ -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:
index 2c7b81f..074e15f 100644 (file)
@@ -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
index 3078de0..77d3dea 100644 (file)
@@ -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
+
+
index a28c0f6..73e0a0c 100644 (file)
@@ -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()