aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconf/01_testcases.conf8
-rw-r--r--conf/02_vswitch.conf2
-rw-r--r--conf/integration/01_testcases.conf40
-rw-r--r--core/vnf_controller.py9
-rw-r--r--core/vswitch_controller_pvp.py2
-rw-r--r--core/vswitch_controller_pvvp.py2
-rwxr-xr-xdocs/configguide/installation.rst39
-rwxr-xr-xsrc/dpdk/Makefile4
-rw-r--r--src/ovs/daemon.py17
-rwxr-xr-xsrc/qemu/Makefile8
-rw-r--r--testcases/testcase.py4
-rw-r--r--tools/pkt_gen/trafficgen/trafficgenhelper.py2
-rwxr-xr-xtools/pkt_gen/xena/xena.py2
-rw-r--r--tools/systeminfo.py8
-rw-r--r--tools/tasks.py63
-rw-r--r--vnfs/qemu/qemu.py28
-rw-r--r--vnfs/vnf/vnf.py9
-rwxr-xr-xvsperf2
-rw-r--r--vswitches/ovs.py2
19 files changed, 181 insertions, 70 deletions
diff --git a/conf/01_testcases.conf b/conf/01_testcases.conf
index 148171fd..23a3ae57 100755
--- a/conf/01_testcases.conf
+++ b/conf/01_testcases.conf
@@ -28,10 +28,12 @@
# "Frame Modification": "vlan" # One of the supported frame modifications:
# # vlan, mpls, mac, dscp, ttl, ip_addr,
# # ip_port.
-# "biDirectional": [true|false], # Specifies if generated traffic will be
-# # full-duplex (true) or half-duplex (false)
+# "biDirectional": ["True"|"False"]
+# # Specifies if generated traffic will be
+# # full-duplex (True) or half-duplex (False)
# # It can be overridden by cli option bidirectional.
-# # Default value is "false".
+# # Default value is "False". Must be of type
+# # string.
# "MultiStream": 0-65535 # Optional. Defines number of flows simulated
# # by traffic generator. Value 0 disables
# # MultiStream feature
diff --git a/conf/02_vswitch.conf b/conf/02_vswitch.conf
index d36d1786..67f96991 100644
--- a/conf/02_vswitch.conf
+++ b/conf/02_vswitch.conf
@@ -71,7 +71,7 @@ VHOST_USER_SOCKS = ['/tmp/dpdkvhostuser0', '/tmp/dpdkvhostuser1',
# hardware configuration, like cpu numbering and NUMA.
VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4', '--socket-mem 1024,0']
-VSWITCHD_VANILLA_ARGS = ['--pidfile']
+VSWITCHD_VANILLA_ARGS = []
# use full module path to load module matching OVS version built from the source
VSWITCH_VANILLA_KERNEL_MODULES = ['libcrc32c', 'ip_tunnel', 'vxlan', 'gre', 'nf_conntrack', 'nf_defrag_ipv4', 'nf_defrag_ipv6', os.path.join(OVS_DIR_VANILLA, 'datapath/linux/openvswitch.ko')]
diff --git a/conf/integration/01_testcases.conf b/conf/integration/01_testcases.conf
index e9257ae0..2edbe08b 100644
--- a/conf/integration/01_testcases.conf
+++ b/conf/integration/01_testcases.conf
@@ -136,7 +136,7 @@ INTEGRATION_TESTS = [
"Name": "overlay_p2p_tput",
"Traffic Type": "rfc2544",
"Deployment": "op2p",
- "biDirectional": False,
+ "biDirectional": 'False',
"Tunnel Type": SUPPORTED_TUNNELING_PROTO[0],
"Tunnel Operation": "encapsulation",
"Description": "Overlay Encapsulation Throughput RFC2544 Test",
@@ -145,7 +145,7 @@ INTEGRATION_TESTS = [
"Name": "overlay_p2p_cont",
"Traffic Type": "continuous",
"Deployment": "op2p",
- "biDirectional": False,
+ "biDirectional": 'False',
"Tunnel Type": SUPPORTED_TUNNELING_PROTO[0],
"Tunnel Operation": "encapsulation",
"Description": "Overlay Encapsulation Continuous Stream",
@@ -154,7 +154,7 @@ INTEGRATION_TESTS = [
"Name": "overlay_p2p_decap_tput",
"Traffic Type": "rfc2544",
"Deployment": "op2p",
- "biDirectional": False,
+ "biDirectional": 'False',
"Tunnel Type": SUPPORTED_TUNNELING_PROTO[0],
"Tunnel Operation": "decapsulation",
"Description": "Overlay Decapsulation Throughput RFC2544 Test",
@@ -163,7 +163,7 @@ INTEGRATION_TESTS = [
"Name": "overlay_p2p_decap_cont",
"Traffic Type": "continuous",
"Deployment": "op2p",
- "biDirectional": False,
+ "biDirectional": 'False',
"Tunnel Type": SUPPORTED_TUNNELING_PROTO[0],
"Tunnel Operation": "decapsulation",
"Description": "Overlay Decapsulation Continuous Stream",
@@ -264,7 +264,7 @@ INTEGRATION_TESTS = [
"Description": "vSwitch - configure switch and execute RFC2544 throughput test",
"TestSteps": STEP_VSWITCH_P2P_FLOWS_INIT +
[
- ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : 'True'}],
] +
STEP_VSWITCH_P2P_FLOWS_FINIT
},
@@ -274,7 +274,7 @@ INTEGRATION_TESTS = [
"Description": "vSwitch - configure switch and execute RFC2544 back2back test",
"TestSteps": STEP_VSWITCH_P2P_FLOWS_INIT +
[
- ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : 'True'}],
] +
STEP_VSWITCH_P2P_FLOWS_FINIT
},
@@ -284,7 +284,7 @@ INTEGRATION_TESTS = [
"Description": "vSwitch - configure switch and execute continuous stream test",
"TestSteps": STEP_VSWITCH_P2P_FLOWS_INIT +
[
- ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : 'True'}],
] +
STEP_VSWITCH_P2P_FLOWS_FINIT
},
@@ -306,7 +306,7 @@ INTEGRATION_TESTS = [
"TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT +
[
['vnf', 'start'],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : 'True'}],
['vnf', 'stop'],
] +
STEP_VSWITCH_PVP_FLOWS_FINIT
@@ -318,7 +318,7 @@ INTEGRATION_TESTS = [
"TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT +
[
['vnf', 'start'],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : 'True'}],
['vnf', 'stop'],
] +
STEP_VSWITCH_PVP_FLOWS_FINIT
@@ -330,7 +330,7 @@ INTEGRATION_TESTS = [
"TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT +
[
['vnf', 'start'],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : 'True'}],
['vnf', 'stop'],
] +
STEP_VSWITCH_PVP_FLOWS_FINIT
@@ -342,9 +342,9 @@ INTEGRATION_TESTS = [
"TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT +
[
['vnf', 'start'],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : True}],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : True}],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : 'True'}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : 'True'}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : 'True'}],
['vnf', 'stop'],
] +
STEP_VSWITCH_PVP_FLOWS_FINIT
@@ -370,7 +370,7 @@ INTEGRATION_TESTS = [
[
['vnf1', 'start'],
['vnf2', 'start'],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : 'True'}],
['vnf1', 'stop'],
['vnf2', 'stop'],
] +
@@ -384,7 +384,7 @@ INTEGRATION_TESTS = [
[
['vnf1', 'start'],
['vnf2', 'start'],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : 'True'}],
['vnf1', 'stop'],
['vnf2', 'stop'],
] +
@@ -398,7 +398,7 @@ INTEGRATION_TESTS = [
[
['vnf1', 'start'],
['vnf2', 'start'],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : 'True'}],
['vnf1', 'stop'],
['vnf2', 'stop'],
] +
@@ -412,9 +412,9 @@ INTEGRATION_TESTS = [
[
['vnf1', 'start'],
['vnf2', 'start'],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : True}],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : True}],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : True}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput', 'bidir' : 'True'}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : 'True'}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : 'True'}],
['vnf1', 'stop'],
['vnf2', 'stop'],
] +
@@ -434,7 +434,7 @@ INTEGRATION_TESTS = [
# "TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT +
# [
# ['vnf', 'start'],
-# ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : True}],
+# ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : 'True'}],
# ['vnf', 'stop'],
# ] +
# STEP_VSWITCH_PVP_FLOWS_FINIT
diff --git a/core/vnf_controller.py b/core/vnf_controller.py
index 39a63044..8800ccaf 100644
--- a/core/vnf_controller.py
+++ b/core/vnf_controller.py
@@ -15,6 +15,7 @@
"""
import logging
+import pexpect
from vnfs.vnf.vnf import IVnf
class VnfController(object):
@@ -68,8 +69,12 @@ class VnfController(object):
"""
self._logger.debug('start ' + str(len(self._vnfs)) +
' VNF[s] with ' + ' '.join(map(str, self._vnfs)))
- for vnf in self._vnfs:
- vnf.start()
+ try:
+ for vnf in self._vnfs:
+ vnf.start()
+ except pexpect.TIMEOUT:
+ self.stop()
+ raise
def stop(self):
"""Stops all VNFs set-up by __init__.
diff --git a/core/vswitch_controller_pvp.py b/core/vswitch_controller_pvp.py
index 0c98cc7f..a4f61961 100644
--- a/core/vswitch_controller_pvp.py
+++ b/core/vswitch_controller_pvp.py
@@ -77,7 +77,7 @@ class VswitchControllerPVP(IVswitchController):
self._vswitch.add_flow(bridge, flow1)
self._vswitch.add_flow(bridge, flow2)
- if self._traffic['bidir']:
+ if self._traffic['bidir'] == 'True':
flow3 = add_ports_to_flow(flow_template, phy2_number,
vport2_number)
flow4 = add_ports_to_flow(flow_template, vport1_number,
diff --git a/core/vswitch_controller_pvvp.py b/core/vswitch_controller_pvvp.py
index c79ad9a3..729aca3f 100644
--- a/core/vswitch_controller_pvvp.py
+++ b/core/vswitch_controller_pvvp.py
@@ -82,7 +82,7 @@ class VswitchControllerPVVP(IVswitchController):
self._vswitch.add_flow(bridge, flow2)
self._vswitch.add_flow(bridge, flow3)
- if self._traffic['bidir']:
+ if self._traffic['bidir'] == 'True':
flow4 = add_ports_to_flow(flow_template, phy2_number,
vport4_number)
flow5 = add_ports_to_flow(flow_template, vport3_number,
diff --git a/docs/configguide/installation.rst b/docs/configguide/installation.rst
index 354979b0..d6161b9a 100755
--- a/docs/configguide/installation.rst
+++ b/docs/configguide/installation.rst
@@ -119,3 +119,42 @@ running any of the above. For example:
.. _virtualenv: https://virtualenv.readthedocs.org/en/latest/
.. _vloop-vnf-ubuntu-14.04_20160303: http://artifacts.opnfv.org/vswitchperf/vnf/vloop-vnf-ubuntu-14.04_20160303.qcow2
.. _vloop-vnf-ubuntu-14.04_20151216: http://artifacts.opnfv.org/vswitchperf/vnf/vloop-vnf-ubuntu-14.04_20151216.qcow2
+
+Hugepage Configuration
+----------------------
+
+Systems running vsperf with either dpdk and/or tests with guests must configure
+hugepage amounts to support running these configurations. It is recommended
+to configure 1GB hugepages as the pagesize.
+
+The amount of hugepages needed depends on your configuration files in vsperf.
+Each guest image requires 4096 by default according to the default settings in
+the ``04_vnf.conf`` file.
+
+.. code:: bash
+
+ GUEST_MEMORY = ['4096', '4096']
+
+The dpdk startup parameters also require an amount of hugepages depending on
+your configuration in the ``02_vswitch.conf`` file.
+
+.. code:: bash
+
+ VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4', '--socket-mem 1024,1024']
+
+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
+within vsperf if the pagesize is set correctly to 1GB.
+
+Depending on your OS selection configuration of hugepages may vary. Please refer
+to your OS documentation to set hugepages correctly. It is recommended to set
+the required amount of hugepages to be allocated by default on reboots.
+
+Information on hugepage requirements for dpdk can be found at
+http://dpdk.org/doc/guides/linux_gsg/sys_reqs.html
+
+You can review your hugepage amounts by executing the following command
+
+.. code:: bash
+
+ cat /proc/meminfo | grep Huge
diff --git a/src/dpdk/Makefile b/src/dpdk/Makefile
index 25ec3f12..e21e7999 100755
--- a/src/dpdk/Makefile
+++ b/src/dpdk/Makefile
@@ -29,7 +29,6 @@ ifndef VHOST_USER
endif
WORK_DIR = dpdk
TAG_DONE_FLAG = $(WORK_DIR)/.$(DPDK_TAG).tag.done
-DPDK_VANILLA = ../../src_vanilla/dpdk
DPDK_CUSE = ../../src_cuse/dpdk
# the name has been changed from version to version
@@ -70,7 +69,6 @@ clean:
$(AT)cd $(WORK_DIR) && git clean -xfd *.o
clobber:
$(AT)rm -rf $(WORK_DIR)
- $(AT)rm -rf $(DPDK_VANILLA)
$(AT)rm -rf $(DPDK_CUSE)
# distclean is for developer who would like to keep the
@@ -86,8 +84,6 @@ sanity:
$(WORK_DIR):
$(AT)git clone $(DPDK_URL)
- $(AT)mkdir -p $(DPDK_VANILLA)
- $(AT)cp -rf ./* $(DPDK_VANILLA)
$(AT)mkdir -p $(DPDK_CUSE)
$(AT)cp -rf ./* $(DPDK_CUSE)
diff --git a/src/ovs/daemon.py b/src/ovs/daemon.py
index 089bc7a4..f9b037b2 100644
--- a/src/ovs/daemon.py
+++ b/src/ovs/daemon.py
@@ -38,6 +38,7 @@ class VSwitchd(tasks.Process):
_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):
@@ -55,7 +56,10 @@ class VSwitchd(tasks.Process):
vswitchd_args = vswitchd_args or []
ovs_vswitchd_bin = os.path.join(
settings.getValue('OVS_DIR'), 'vswitchd', 'ovs-vswitchd')
- self._cmd = ['sudo', '-E', ovs_vswitchd_bin] + vswitchd_args
+ 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
@@ -77,15 +81,19 @@ class VSwitchd(tasks.Process):
self._kill_ovsdb()
raise exc
- def kill(self, signal='-15', sleep=2):
+ 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()
+ 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
@@ -144,8 +152,7 @@ class VSwitchd(tasks.Process):
self._logger.info("Killing ovsdb with pid: " + ovsdb_pid)
if ovsdb_pid:
- tasks.run_task(['sudo', 'kill', '-15', str(ovsdb_pid)],
- self._logger, 'Killing ovsdb-server...')
+ tasks.terminate_task(ovsdb_pid, logger=self._logger)
@staticmethod
def get_db_sock_path():
diff --git a/src/qemu/Makefile b/src/qemu/Makefile
index 4603b273..1bf8a8d0 100755
--- a/src/qemu/Makefile
+++ b/src/qemu/Makefile
@@ -28,8 +28,6 @@ INSTALL_TARGET = force_make force_install
CONFIG_CMD =
CONFIG_CMD += ./configure
CONFIG_CMD += --target-list="x86_64-softmmu"
-QEMU_VANILLA = ../../src_vanilla/qemu
-QEMU_CUSE = ../../src_cuse/qemu
all: force_make
@@ -55,8 +53,6 @@ clean:
$(AT)cd $(WORK_DIR) && git clean -xfd *.o
clobber:
$(AT)rm -rf $(WORK_DIR)
- $(AT)rm -rf $(QEMU_VANILLA)
- $(AT)rm -rf $(QEMU_CUSE)
# distclean is for developer who would like to keep the
# clone git repo, saving time to fetch again from url
@@ -73,10 +69,6 @@ $(WORK_DIR)/configure: $(TAG_DONE_FLAG)
$(WORK_DIR):
$(AT)git clone $(QEMU_URL)
- $(AT)mkdir -p $(QEMU_VANILLA)
- $(AT)cp -rf ./* $(QEMU_VANILLA)
- $(AT)mkdir -p $(QEMU_CUSE)
- $(AT)cp -rf ./* $(QEMU_CUSE)
$(TAG_DONE_FLAG): $(WORK_DIR)
$(AT)cd $(WORK_DIR); git checkout $(QEMU_TAG)
diff --git a/testcases/testcase.py b/testcases/testcase.py
index f7908af9..5b9ead69 100644
--- a/testcases/testcase.py
+++ b/testcases/testcase.py
@@ -82,6 +82,10 @@ class TestCase(object):
bidirectional = cfg.get('biDirectional', TRAFFIC_DEFAULTS['bidir'])
bidirectional = get_test_param('bidirectional', bidirectional)
+ if not isinstance(bidirectional, str):
+ raise TypeError(
+ 'Bi-dir value must be of type string in testcase configuration')
+ bidirectional = bidirectional.title() # Keep things consistent
traffic_type = cfg.get('Traffic Type', TRAFFIC_DEFAULTS['traffic_type'])
traffic_type = get_test_param('traffic_type', traffic_type)
diff --git a/tools/pkt_gen/trafficgen/trafficgenhelper.py b/tools/pkt_gen/trafficgen/trafficgenhelper.py
index 0a240579..90c77b09 100644
--- a/tools/pkt_gen/trafficgen/trafficgenhelper.py
+++ b/tools/pkt_gen/trafficgen/trafficgenhelper.py
@@ -23,7 +23,7 @@ CMD_PREFIX = 'gencmd : '
TRAFFIC_DEFAULTS = {
'traffic_type' : 'rfc2544',
'frame_rate' : 100,
- 'bidir' : False,
+ 'bidir' : 'False', # will be passed as string in title format to tgen
'multistream' : 0,
'stream_type' : 'L4',
'pre_installed_flows' : 'No', # used by vswitch implementation
diff --git a/tools/pkt_gen/xena/xena.py b/tools/pkt_gen/xena/xena.py
index 67ac5652..d29fc362 100755
--- a/tools/pkt_gen/xena/xena.py
+++ b/tools/pkt_gen/xena/xena.py
@@ -182,7 +182,7 @@ class Xena(ITrafficGenerator):
flows=self._params['traffic']['multistream'],
multistream_layer=self._params['traffic']['stream_type'])
# set duplex mode
- if bool(self._params['traffic']['bidir']):
+ if self._params['traffic']['bidir'] == "True":
j_file.set_topology_mesh()
else:
j_file.set_topology_blocks()
diff --git a/tools/systeminfo.py b/tools/systeminfo.py
index ba490946..9d8eb5cb 100644
--- a/tools/systeminfo.py
+++ b/tools/systeminfo.py
@@ -168,6 +168,14 @@ def get_pid(proc_name_str):
"""
return get_pids([proc_name_str])
+def pid_isalive(pid):
+ """ Checks if given PID is alive
+
+ :param pid: PID of the process
+ :returns: True if given process is running, False otherwise
+ """
+ return os.path.isdir('/proc/' + str(pid))
+
# This function uses long switch per purpose, so let us suppress pylint warning too-many-branches
# pylint: disable=R0912
def get_version(app_name):
diff --git a/tools/tasks.py b/tools/tasks.py
index 90b7e553..dda5217d 100644
--- a/tools/tasks.py
+++ b/tools/tasks.py
@@ -26,6 +26,7 @@ import locale
import time
from conf import settings
+from tools import systeminfo
CMD_PREFIX = 'cmd : '
@@ -150,6 +151,55 @@ def run_interactive_task(cmd, logger, msg):
return child
+def terminate_task_subtree(pid, signal='-15', sleep=10, logger=None):
+ """Terminate given process and all its children
+
+ Function will sent given signal to the process. In case
+ that process will not terminate within given sleep interval
+ and signal was not SIGKILL, then process will be killed by SIGKILL.
+ After that function will check if all children of the process
+ are terminated and if not the same terminating procedure is applied
+ on any living child (only one level of children is considered).
+
+ :param pid: Process ID to terminate
+ :param signal: Signal to be sent to the process
+ :param sleep: Maximum delay in seconds after signal is sent
+ :param logger: Logger to write details to
+ """
+ try:
+ output = subprocess.check_output("pgrep -P " + str(pid), shell=True).decode().rstrip('\n')
+ except subprocess.CalledProcessError:
+ output = ""
+
+ terminate_task(pid, signal, sleep, logger)
+
+ # just for case children were kept alive
+ children = output.split('\n')
+ for child in children:
+ terminate_task(child, signal, sleep, logger)
+
+def terminate_task(pid, signal='-15', sleep=10, logger=None):
+ """Terminate process with given pid
+
+ Function will sent given signal to the process. In case
+ that process will not terminate within given sleep interval
+ and signal was not SIGKILL, then process will be killed by SIGKILL.
+
+ :param pid: Process ID to terminate
+ :param signal: Signal to be sent to the process
+ :param sleep: Maximum delay in seconds after signal is sent
+ :param logger: Logger to write details to
+ """
+ if systeminfo.pid_isalive(pid):
+ run_task(['sudo', 'kill', signal, str(pid)], logger)
+ logger.debug('Wait for process %s to terminate after signal %s', pid, signal)
+ for dummy in range(sleep):
+ time.sleep(1)
+ if not systeminfo.pid_isalive(pid):
+ break
+
+ if signal.lstrip('-').upper() not in ('9', 'KILL', 'SIGKILL') and systeminfo.pid_isalive(pid):
+ terminate_task(pid, '-9', sleep, logger)
class Process(object):
"""Control an instance of a long-running process.
@@ -242,17 +292,14 @@ class Process(object):
self.kill()
raise exc
- def kill(self, signal='-15', sleep=2):
+ def kill(self, signal='-15', sleep=10):
"""Kill process instance if it is alive.
:param signal: signal to be sent to the process
:param sleep: delay in seconds after signal is sent
"""
- if self._child and self._child.isalive():
- run_task(['sudo', 'kill', signal, str(self._child.pid)],
- self._logger)
- self._logger.debug('Wait for process to terminate')
- time.sleep(sleep)
+ if self.is_running():
+ terminate_task_subtree(self._child.pid, signal, sleep, self._logger)
if self.is_relinquished():
self._relinquish_thread.join()
@@ -275,7 +322,7 @@ class Process(object):
:returns: True if process is running, else False
"""
- return self._child is not None
+ return self._child and self._child.isalive()
def _affinitize_pid(self, core, pid):
"""Affinitize a process with ``pid`` to ``core``.
@@ -298,7 +345,7 @@ class Process(object):
"""
self._logger.info('Affinitizing process')
- if self._child and self._child.isalive():
+ if self.is_running():
self._affinitize_pid(core, self._child.pid)
class ContinueReadPrintLoop(threading.Thread):
diff --git a/vnfs/qemu/qemu.py b/vnfs/qemu/qemu.py
index c735062f..d108dc9a 100644
--- a/vnfs/qemu/qemu.py
+++ b/vnfs/qemu/qemu.py
@@ -21,6 +21,7 @@ import locale
import re
import subprocess
import time
+import pexpect
from conf import settings as S
from conf import get_test_param
@@ -133,15 +134,24 @@ class IVnfQemu(IVnf):
"""
Stops VNF instance gracefully first.
"""
- # exit testpmd if needed
- if self._guest_loopback == 'testpmd':
- self.execute_and_wait('stop', 120, "Done")
- self.execute_and_wait('quit', 120, "bye")
-
- # turn off VM
- self.execute_and_wait('poweroff', 120, "Power down")
- # VM OS is off, but wait until qemu shutdowns
- time.sleep(2)
+ try:
+ # exit testpmd if needed
+ if self._guest_loopback == 'testpmd':
+ self.execute_and_wait('stop', 120, "Done")
+ self.execute_and_wait('quit', 120, "bye")
+
+ # turn off VM
+ self.execute_and_wait('poweroff', 120, "Power down")
+
+ except pexpect.TIMEOUT:
+ self.kill()
+
+ # wait until qemu shutdowns
+ self._logger.debug('Wait for QEMU to terminate')
+ for dummy in range(30):
+ time.sleep(1)
+ if not self.is_running():
+ break
# just for case that graceful shutdown failed
super(IVnfQemu, self).stop()
diff --git a/vnfs/vnf/vnf.py b/vnfs/vnf/vnf.py
index 3dae2733..1410a0c4 100644
--- a/vnfs/vnf/vnf.py
+++ b/vnfs/vnf/vnf.py
@@ -51,11 +51,12 @@ class IVnf(tasks.Process):
"""
Stops VNF instance.
"""
- self._logger.info('Killing VNF...')
+ if self.is_running():
+ self._logger.info('Killing VNF...')
- # force termination of VNF and wait for it to terminate; It will avoid
- # sporadic reboot of host. (caused by hugepages or DPDK ports)
- super(IVnf, self).kill(signal='-9', sleep=10)
+ # force termination of VNF and wait for it to terminate; It will avoid
+ # sporadic reboot of host. (caused by hugepages or DPDK ports)
+ super(IVnf, self).kill(signal='-9', sleep=10)
def execute(self, cmd, delay=0):
"""
diff --git a/vsperf b/vsperf
index 98bc7db0..789e5df8 100755
--- a/vsperf
+++ b/vsperf
@@ -610,7 +610,7 @@ def main():
# set traffic details, so they can be passed to traffic ctl
traffic = copy.deepcopy(TRAFFIC_DEFAULTS)
traffic.update({'traffic_type': get_test_param('traffic_type', 'rfc2544'),
- 'bidir': get_test_param('bidirectional', False),
+ 'bidir': get_test_param('bidirectional', 'False'),
'multistream': int(get_test_param('multistream', 0)),
'stream_type': get_test_param('stream_type', 'L4'),
'frame_rate': int(get_test_param('iload', 100))})
diff --git a/vswitches/ovs.py b/vswitches/ovs.py
index 06dc7a1a..dd49a1fc 100644
--- a/vswitches/ovs.py
+++ b/vswitches/ovs.py
@@ -21,7 +21,7 @@ from conf import settings
from vswitches.vswitch import IVSwitch
from src.ovs import OFBridge, flow_key, flow_match
-_VSWITCHD_CONST_ARGS = ['--', '--pidfile', '--log-file']
+_VSWITCHD_CONST_ARGS = []
class IVSwitchOvs(IVSwitch):
"""Open vSwitch base class implementation