Configuration of DPDK options in ovs-vswitchd has changed.
Previously used option --dpdk was deprecated and all DPDK
related options have to be configured through ovsdb via ovs-vsctl
calls. VSPERF was modified to detect and use correct version
of DPDK configuration. New configuration options should
be put into VSWITCHD_DPDK_CONFIG dictionary.
VSPERF classes specific to OVS were refactored.
Change-Id: Ia3fad5906221439f477638f1f9734289dbf737bb
JIRA: VSPERF-291
Signed-off-by: Martin Klozik <martinx.klozik@intel.com>
Reviewed-by: Maryam Tahhan <maryam.tahhan@intel.com>
Reviewed-by: Al Morton <acmorton@att.com>
Reviewed-by: Christian Trautman <ctrautma@redhat.com>
Reviewed-by: Brian Castelli <brian.castelli@spirent.com>
# ############################
# These are DPDK EAL parameters and they may need to be changed depending on
# hardware configuration, like cpu numbering and NUMA.
+#
+# parameters used for legacy DPDK configuration through '--dpdk' option of ovs-vswitchd
+# e.g. ovs-vswitchd --dpdk --socket-mem 1024,0
VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4', '--socket-mem 1024,0']
+# options used for new type of OVS configuration via calls to ovs-vsctl
+# e.g. ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem="1024,0"
+VSWITCHD_DPDK_CONFIG = {
+ 'dpdk-init' : 'true',
+ 'dpdk-lcore-mask' : '0x4',
+ 'dpdk-socket-mem' : '1024,0',
+}
+# Note: VSPERF will automatically detect, which type of DPDK configuration should
+# be used.
+
+# parameters passed to ovs-vswitchd in case that OvsVanilla is selected
VSWITCHD_VANILLA_ARGS = []
# use full module path to load module matching OVS version built from the source
.. code:: bash
VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4', '--socket-mem 1024,1024']
+ VSWITCHD_DPDK_CONFIG = {
+ 'dpdk-init' : 'true',
+ 'dpdk-lcore-mask' : '0x4',
+ 'dpdk-socket-mem' : '1024,1024',
+ }
+
+Note: Option VSWITCHD_DPDK_ARGS is used for vswitchd, which supports --dpdk
+parameter. In recent vswitchd versions, option VSWITCHD_DPDK_CONFIG will be
+used to configure vswitchd via ovs-vsctl calls.
With the --socket-mem argument set to use 1 hugepage on the specified sockets as
seen above, the configuration will need 9 hugepages total to run all tests
.. code-block:: console
VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4', '--socket-mem 1024,0']
+ VSWITCHD_DPDK_CONFIG = {
+ 'dpdk-init' : 'true',
+ 'dpdk-lcore-mask' : '0x4',
+ 'dpdk-socket-mem' : '1024,0',
+ }
+
+Note: Option VSWITCHD_DPDK_ARGS is used for vswitchd, which supports --dpdk
+parameter. In recent vswitchd versions, option VSWITCHD_DPDK_CONFIG will be
+used to configure vswitchd via ovs-vsctl calls.
+
More information
^^^^^^^^^^^^^^^^
"""
-from src.ovs.daemon import *
from src.ovs.ofctl import *
from src.ovs.dpctl import *
+++ /dev/null
-# Copyright 2015 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.
-
-"""Class wrapper for controlling an OVS instance.
-
-Wraps a pair of ``ovs-vswitchd`` and ``ovsdb-server`` processes.
-"""
-
-import os
-import logging
-import pexpect
-
-from conf import settings
-from tools import tasks
-
-_OVS_VAR_DIR = settings.getValue('OVS_VAR_DIR')
-_OVS_ETC_DIR = settings.getValue('OVS_ETC_DIR')
-
-_LOG_FILE_VSWITCHD = os.path.join(
- settings.getValue('LOG_DIR'), settings.getValue('LOG_FILE_VSWITCHD'))
-
-class VSwitchd(tasks.Process):
- """Class wrapper for controlling an OVS instance.
-
- Wraps a pair of ``ovs-vswitchd`` and ``ovsdb-server`` processes.
- """
- _ovsdb_pid = None
- _logfile = _LOG_FILE_VSWITCHD
- _ovsdb_pidfile_path = os.path.join(settings.getValue('LOG_DIR'), "ovsdb_pidfile.pid")
- _vswitchd_pidfile_path = os.path.join(settings.getValue('LOG_DIR'), "vswitchd_pidfile.pid")
- _proc_name = 'ovs-vswitchd'
-
- def __init__(self, timeout=30, vswitchd_args=None, expected_cmd=None):
- """Initialise the wrapper with a specific start timeout and extra
- parameters.
-
- :param timeout: Timeout to wait for application to start.
- :param vswitchd_args: Command line parameters for vswitchd.
-
- :returns: None
- """
- self._logger = logging.getLogger(__name__)
- self._timeout = timeout
- self._expect = expected_cmd
- vswitchd_args = vswitchd_args or []
- ovs_vswitchd_bin = os.path.join(
- settings.getValue('OVS_DIR'), 'vswitchd', 'ovs-vswitchd')
- sep = ['--'] if '--dpdk' in vswitchd_args else []
- self._cmd = ['sudo', '-E', ovs_vswitchd_bin] + vswitchd_args + sep + \
- ['--pidfile=' + self._vswitchd_pidfile_path, '--overwrite-pidfile',
- '--log-file=' + self._logfile]
-
- # startup/shutdown
-
- def start(self):
- """ Start ``ovsdb-server`` and ``ovs-vswitchd`` instance.
-
- :returns: None
- :raises: pexpect.EOF, pexpect.TIMEOUT
- """
-
- self._reset_ovsdb()
- self._start_ovsdb() # this has to be started first
-
- try:
- super(VSwitchd, self).start()
- self.relinquish()
- except (pexpect.EOF, pexpect.TIMEOUT) as exc:
- logging.error("Exception during VSwitch start.")
- self._kill_ovsdb()
- raise exc
-
- def kill(self, signal='-15', sleep=10):
- """Kill ``ovs-vswitchd`` instance if it is alive.
-
- :returns: None
- """
- self._logger.info('Killing ovs-vswitchd...')
- with open(self._vswitchd_pidfile_path, "r") as pidfile:
- vswitchd_pid = pidfile.read().strip()
- tasks.terminate_task(vswitchd_pid, logger=self._logger)
-
- self._kill_ovsdb() # ovsdb must be killed after vswitchd
-
- # just for case, that sudo envelope has not terminated
- super(VSwitchd, self).kill(signal, sleep)
-
- # helper functions
-
- def _reset_ovsdb(self):
- """Reset system for 'ovsdb'.
-
- :returns: None
- """
- self._logger.info('Resetting system after last run...')
-
- tasks.run_task(['sudo', 'rm', '-rf', _OVS_VAR_DIR], self._logger)
- tasks.run_task(['sudo', 'mkdir', '-p', _OVS_VAR_DIR], self._logger)
- tasks.run_task(['sudo', 'rm', '-rf', _OVS_ETC_DIR], self._logger)
- tasks.run_task(['sudo', 'mkdir', '-p', _OVS_ETC_DIR], self._logger)
-
- tasks.run_task(['sudo', 'rm', '-f',
- os.path.join(_OVS_ETC_DIR, 'conf.db')],
- self._logger)
-
- self._logger.info('System reset after last run.')
-
- def _start_ovsdb(self):
- """Start ``ovsdb-server`` instance.
-
- :returns: None
- """
- ovsdb_tool_bin = os.path.join(
- settings.getValue('OVS_DIR'), 'ovsdb', 'ovsdb-tool')
- tasks.run_task(['sudo', ovsdb_tool_bin, 'create',
- os.path.join(_OVS_ETC_DIR, 'conf.db'),
- os.path.join(settings.getValue('OVS_DIR'), 'vswitchd',
- 'vswitch.ovsschema')],
- self._logger,
- 'Creating ovsdb configuration database...')
-
- ovsdb_server_bin = os.path.join(
- settings.getValue('OVS_DIR'), 'ovsdb', 'ovsdb-server')
-
- tasks.run_background_task(
- ['sudo', ovsdb_server_bin,
- '--remote=punix:%s' % os.path.join(_OVS_VAR_DIR, 'db.sock'),
- '--remote=db:Open_vSwitch,Open_vSwitch,manager_options',
- '--pidfile=' + self._ovsdb_pidfile_path, '--overwrite-pidfile'],
- self._logger,
- 'Starting ovsdb-server...')
-
- def _kill_ovsdb(self):
- """Kill ``ovsdb-server`` instance.
-
- :returns: None
- """
- with open(self._ovsdb_pidfile_path, "r") as pidfile:
- ovsdb_pid = pidfile.read().strip()
-
- self._logger.info("Killing ovsdb with pid: " + ovsdb_pid)
-
- if ovsdb_pid:
- tasks.terminate_task(ovsdb_pid, logger=self._logger)
-
- @staticmethod
- def get_db_sock_path():
- """Method returns location of db.sock file
-
- :returns: path to db.sock file.
- """
- return os.path.join(_OVS_VAR_DIR, 'db.sock')
def run_vsctl(self, args, check_error=False):
"""Run ``ovs-vsctl`` with supplied arguments.
+ In case that timeout is set to -1, then ovs-vsctl
+ will be called with --no-wait option.
+
:param args: Arguments to pass to ``ovs-vsctl``
:param check_error: Throw exception on error
:return: None
"""
- cmd = ['sudo', _OVS_VSCTL_BIN, '--timeout', str(self.timeout)] + args
+ if self.timeout == -1:
+ cmd = ['sudo', _OVS_VSCTL_BIN, '--no-wait'] + args
+ else:
+ cmd = ['sudo', _OVS_VSCTL_BIN, '--timeout', str(self.timeout)] + args
return tasks.run_task(
cmd, self.logger, 'Running ovs-vsctl...', check_error)
import logging
import re
+import os
+import pexpect
from conf import settings
from vswitches.vswitch import IVSwitch
from src.ovs import OFBridge, flow_key, flow_match
+from tools import tasks
-_VSWITCHD_CONST_ARGS = []
+_OVS_VAR_DIR = settings.getValue('OVS_VAR_DIR')
+_OVS_ETC_DIR = settings.getValue('OVS_ETC_DIR')
-class IVSwitchOvs(IVSwitch):
+class IVSwitchOvs(IVSwitch, tasks.Process):
"""Open vSwitch base class implementation
The method docstrings document only considerations specific to this
implementation. For generic information of the nature of the methods,
see the interface.
"""
+ _logfile = os.path.join(settings.getValue('LOG_DIR'), settings.getValue('LOG_FILE_VSWITCHD'))
+ _ovsdb_pidfile_path = os.path.join(settings.getValue('LOG_DIR'), "ovsdb_pidfile.pid")
+ _vswitchd_pidfile_path = os.path.join(settings.getValue('LOG_DIR'), "vswitchd_pidfile.pid")
+ _proc_name = 'ovs-vswitchd'
def __init__(self):
"""See IVswitch for general description
"""
- self._vswitchd = None
self._logger = logging.getLogger(__name__)
+ self._expect = None
+ self._timeout = 30
self._bridges = {}
- self._vswitchd_args = _VSWITCHD_CONST_ARGS
+ self._vswitchd_args = ['--pidfile=' + self._vswitchd_pidfile_path,
+ '--overwrite-pidfile', '--log-file=' + self._logfile]
+ self._cmd = []
+ self._cmd_template = ['sudo', '-E', os.path.join(settings.getValue('OVS_DIR'),
+ 'vswitchd', 'ovs-vswitchd')]
def start(self):
- """See IVswitch for general description
+ """ Start ``ovsdb-server`` and ``ovs-vswitchd`` instance.
+
+ :raises: pexpect.EOF, pexpect.TIMEOUT
"""
self._logger.info("Starting vswitchd...")
- self._vswitchd.start()
+
+ self._cmd = self._cmd_template + self._vswitchd_args
+
+ # DB must be started before vswitchd
+ self._reset_ovsdb()
+ self._start_ovsdb()
+
+ # DB must be up before vswitchd config is altered
+ self.configure()
+
+ try:
+ tasks.Process.start(self)
+ self.relinquish()
+ except (pexpect.EOF, pexpect.TIMEOUT) as exc:
+ logging.error("Exception during VSwitch start.")
+ self._kill_ovsdb()
+ raise exc
+
self._logger.info("Vswitchd...Started.")
+ def configure(self):
+ """ Configure vswitchd through ovsdb if needed
+ """
+ pass
+
def stop(self):
"""See IVswitch for general description
"""
self._logger.info("Terminating vswitchd...")
- self._vswitchd.kill()
+ self.kill()
self._logger.info("Vswitchd...Terminated.")
def add_switch(self, switch_name, params=None):
cnt = 0
return cnt
+ def kill(self, signal='-15', sleep=10):
+ """Kill ``ovs-vswitchd`` and ``ovs-ovsdb`` instances if they are alive.
+
+ :returns: None
+ """
+ if os.path.isfile(self._vswitchd_pidfile_path):
+ self._logger.info('Killing ovs-vswitchd...')
+ with open(self._vswitchd_pidfile_path, "r") as pidfile:
+ vswitchd_pid = pidfile.read().strip()
+ tasks.terminate_task(vswitchd_pid, logger=self._logger)
+
+ self._kill_ovsdb() # ovsdb must be killed after vswitchd
+
+ # just for case, that sudo envelope has not been terminated yet
+ tasks.Process.kill(self, signal, sleep)
+
+ # helper functions
+
+ def _reset_ovsdb(self):
+ """Reset system for 'ovsdb'.
+
+ :returns: None
+ """
+ self._logger.info('Resetting system after last run...')
+
+ tasks.run_task(['sudo', 'rm', '-rf', _OVS_VAR_DIR], self._logger)
+ tasks.run_task(['sudo', 'mkdir', '-p', _OVS_VAR_DIR], self._logger)
+ tasks.run_task(['sudo', 'rm', '-rf', _OVS_ETC_DIR], self._logger)
+ tasks.run_task(['sudo', 'mkdir', '-p', _OVS_ETC_DIR], self._logger)
+
+ tasks.run_task(['sudo', 'rm', '-f',
+ os.path.join(_OVS_ETC_DIR, 'conf.db')],
+ self._logger)
+
+ self._logger.info('System reset after last run.')
+
+ def _start_ovsdb(self):
+ """Start ``ovsdb-server`` instance.
+
+ :returns: None
+ """
+ ovsdb_tool_bin = os.path.join(
+ settings.getValue('OVS_DIR'), 'ovsdb', 'ovsdb-tool')
+ tasks.run_task(['sudo', ovsdb_tool_bin, 'create',
+ os.path.join(_OVS_ETC_DIR, 'conf.db'),
+ os.path.join(settings.getValue('OVS_DIR'), 'vswitchd',
+ 'vswitch.ovsschema')],
+ self._logger,
+ 'Creating ovsdb configuration database...')
+
+ ovsdb_server_bin = os.path.join(
+ settings.getValue('OVS_DIR'), 'ovsdb', 'ovsdb-server')
+
+ tasks.run_background_task(
+ ['sudo', ovsdb_server_bin,
+ '--remote=punix:%s' % os.path.join(_OVS_VAR_DIR, 'db.sock'),
+ '--remote=db:Open_vSwitch,Open_vSwitch,manager_options',
+ '--pidfile=' + self._ovsdb_pidfile_path, '--overwrite-pidfile'],
+ self._logger,
+ 'Starting ovsdb-server...')
+
+ def _kill_ovsdb(self):
+ """Kill ``ovsdb-server`` instance.
+
+ :returns: None
+ """
+ if os.path.isfile(self._ovsdb_pidfile_path):
+ with open(self._ovsdb_pidfile_path, "r") as pidfile:
+ ovsdb_pid = pidfile.read().strip()
+
+ self._logger.info("Killing ovsdb with pid: " + ovsdb_pid)
+
+ if ovsdb_pid:
+ tasks.terminate_task(ovsdb_pid, logger=self._logger)
+
+ @staticmethod
+ def get_db_sock_path():
+ """Method returns location of db.sock file
+
+ :returns: path to db.sock file.
+ """
+ return os.path.join(_OVS_VAR_DIR, 'db.sock')
+
+ #
+ # validate methods required for integration testcases
+ #
+
def validate_add_switch(self, result, switch_name, params=None):
"""Validate - Create a new logical switch with no ports
"""
"""
import logging
+import subprocess
+import os
+
+from src.ovs import OFBridge
+from src.dpdk import dpdk
from conf import settings
from vswitches.ovs import IVSwitchOvs
-from src.ovs import VSwitchd
-from src.dpdk import dpdk
class OvsDpdkVhost(IVSwitchOvs):
""" Open vSwitch with DPDK support
def __init__(self):
super(OvsDpdkVhost, self).__init__()
self._logger = logging.getLogger(__name__)
+ self._expect = r'EAL: Master l*core \d+ is ready'
+
+ vswitchd_args = []
+
+ # legacy DPDK configuration through --dpdk option of vswitchd
+ if self.old_dpdk_config():
+ vswitchd_args = ['--dpdk'] + settings.getValue('VSWITCHD_DPDK_ARGS')
+ if self._vswitchd_args:
+ self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args
+ else:
+ self._vswitchd_args = vswitchd_args
- self._vswitchd_args = ['--dpdk']
- self._vswitchd_args += settings.getValue('VSWITCHD_DPDK_ARGS')
if settings.getValue('VNF').endswith('Cuse'):
self._logger.info("Inserting VHOST Cuse modules into kernel...")
dpdk.insert_vhost_modules()
- self._vswitchd = VSwitchd(vswitchd_args=self._vswitchd_args,
- expected_cmd=
- r'EAL: Master l*core \d+ is ready')
+ def configure(self):
+ """ Configure vswitchd DPDK options through ovsdb if needed
+ """
+ dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG')
+ if dpdk_config and not self.old_dpdk_config():
+ # enforce calls to ovs-vsctl with --no-wait
+ tmp_br = OFBridge(timeout=-1)
+ for option in dpdk_config:
+ tmp_br.set_db_attribute('Open_vSwitch', '.',
+ 'other_config:' + option, dpdk_config[option])
def start(self):
"""See IVswitch for general description
of_port = bridge.add_port(port_name, params)
return (port_name, of_port)
+
+ @staticmethod
+ def old_dpdk_config():
+ """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
+
+ :returns: True if legacy --dpdk option is supported, otherwise it returns False
+ """
+
+ ovs_vswitchd_bin = os.path.join(settings.getValue('OVS_DIR'), 'vswitchd', 'ovs-vswitchd')
+ try:
+ subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
+ return True
+ except subprocess.CalledProcessError:
+ return False
import logging
from conf import settings
from vswitches.ovs import IVSwitchOvs
-from src.ovs import VSwitchd, DPCtl
+from src.ovs import DPCtl
from tools.module_manager import ModuleManager
from tools import tasks
super(OvsVanilla, self).__init__()
self._ports = list(nic['device'] for nic in settings.getValue('NICS'))
self._logger = logging.getLogger(__name__)
- self._vswitchd_args = ["unix:%s" % VSwitchd.get_db_sock_path()]
+ self._vswitchd_args += ["unix:%s" % self.get_db_sock_path()]
self._vswitchd_args += settings.getValue('VSWITCHD_VANILLA_ARGS')
- self._vswitchd = VSwitchd(vswitchd_args=self._vswitchd_args,
- expected_cmd="db.sock: connected")
- self._bridges = {}
+ self._expect = "db.sock: connected"
self._module_manager = ModuleManager()
def start(self):