summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/02_vswitch.conf5
-rw-r--r--conf/03_traffic.conf4
-rw-r--r--conf/04_vnf.conf5
-rw-r--r--conf/06_pktfwd.conf5
-rw-r--r--conf/10_custom.conf3
-rwxr-xr-xdocs/configguide/installation.rst24
-rw-r--r--docs/configguide/trafficgen.rst2
-rwxr-xr-xdocs/userguide/testusage.rst7
-rwxr-xr-xsystems/centos/build_base_machine.sh2
-rwxr-xr-xsystems/fedora/20/build_base_machine.sh6
-rwxr-xr-xsystems/fedora/21/build_base_machine.sh4
-rwxr-xr-xsystems/fedora/22/build_base_machine.sh6
-rwxr-xr-xsystems/rhel/7.2/build_base_machine.sh4
-rwxr-xr-xsystems/ubuntu/14.04/build_base_machine.sh4
-rwxr-xr-xsystems/ubuntu/build_base_machine.sh2
-rw-r--r--testcases/testcase.py92
-rw-r--r--tools/hugepages.py112
-rw-r--r--tools/namespace.py4
-rw-r--r--tools/pkt_gen/moongen/moongen.py48
-rw-r--r--tools/pkt_gen/xena/XenaDriver.py16
-rw-r--r--vnfs/qemu/qemu_pci_passthrough.py4
-rwxr-xr-xvsperf6
22 files changed, 313 insertions, 52 deletions
diff --git a/conf/02_vswitch.conf b/conf/02_vswitch.conf
index 79f0afbd..e5736138 100644
--- a/conf/02_vswitch.conf
+++ b/conf/02_vswitch.conf
@@ -100,6 +100,11 @@ VSWITCH_BRIDGE_NAME = 'br0'
# directory where hugepages will be mounted on system init
HUGEPAGE_DIR = '/dev/hugepages'
+# If no hugepages are available, try to allocate HUGEPAGE_RAM_ALLOCATION.
+# Default is 2 x 1048576 = 2097152 kB.
+# 10 GB (10485760 kB) or more is recommended for PVP & PVVP testing scenarios.
+HUGEPAGE_RAM_ALLOCATION = 2097152
+
# Sets OVS PMDs core mask to 30 for affinitization to 5th and 6th CPU core.
# Note that the '0x' notation should not be used.
VSWITCH_PMD_CPU_MASK = '30'
diff --git a/conf/03_traffic.conf b/conf/03_traffic.conf
index fb9ce837..a5a8629d 100644
--- a/conf/03_traffic.conf
+++ b/conf/03_traffic.conf
@@ -182,10 +182,14 @@ TRAFFICGEN_XENA_PORT1_GATEWAY = '192.168.199.1'
###################################################
# MoonGen Configuration and Connection Info-- BEGIN
+# Ex: TRAFFICGEN_MOONGEN_HOST_IP_ADDR = "192.10.1.1"
TRAFFICGEN_MOONGEN_HOST_IP_ADDR = ''
TRAFFICGEN_MOONGEN_USER = ''
TRAFFICGEN_MOONGEN_BASE_DIR = ''
TRAFFICGEN_MOONGEN_PORTS = ''
+# Ex. 10 Gbps: TRAFFICGEN_MOONGEN_LINE_SPEED_GBPS = '10'
+# Today only 10 Gbps is supported
+TRAFFICGEN_MOONGEN_LINE_SPEED_GBPS = ''
# MoonGen Configuration and Connection Info-- END
###################################################
diff --git a/conf/04_vnf.conf b/conf/04_vnf.conf
index 0a80c1af..ff110d93 100644
--- a/conf/04_vnf.conf
+++ b/conf/04_vnf.conf
@@ -35,7 +35,10 @@ GUEST_IMAGE = ['', '']
# For 2 VNFs you may use [180, 180]
GUEST_TIMEOUT = [180, 180]
-# packet forwarding mode: io|mac|mac_retry|macswap|flowgen|rxonly|txonly|csum|icmpecho
+# packet forwarding mode supported by testpmd; Please see DPDK documentation
+# for comprehensive list of modes supported by your version.
+# e.g. io|mac|mac_retry|macswap|flowgen|rxonly|txonly|csum|icmpecho|...
+# Note: Option "mac_retry" has been changed to "mac retry" since DPDK v16.07
GUEST_TESTPMD_FWD_MODE = 'csum'
# guest loopback application method; supported options are:
diff --git a/conf/06_pktfwd.conf b/conf/06_pktfwd.conf
index d6a83d07..6175aa6a 100644
--- a/conf/06_pktfwd.conf
+++ b/conf/06_pktfwd.conf
@@ -24,7 +24,10 @@ PKTFWD = 'TestPMD'
# ############################
TESTPMD_ARGS = []
-# packet forwarding mode: io|mac|mac_retry|macswap|flowgen|rxonly|txonly|csum|icmpecho
+# packet forwarding mode supported by testpmd; Please see DPDK documentation
+# for comprehensive list of modes supported by your version.
+# e.g. io|mac|mac_retry|macswap|flowgen|rxonly|txonly|csum|icmpecho|...
+# Note: Option "mac_retry" has been changed to "mac retry" since DPDK v16.07
TESTPMD_FWD_MODE = 'csum'
# checksum calculation layer: ip|udp|tcp|sctp|outer-ip
TESTPMD_CSUM_LAYER = 'ip'
diff --git a/conf/10_custom.conf b/conf/10_custom.conf
index 044339fc..fdb5031a 100644
--- a/conf/10_custom.conf
+++ b/conf/10_custom.conf
@@ -87,6 +87,9 @@ TRAFFICGEN_MOONGEN_HOST_IP_ADDR = ""
TRAFFICGEN_MOONGEN_USER = "root"
TRAFFICGEN_MOONGEN_BASE_DIR = "/root/MoonGen"
TRAFFICGEN_MOONGEN_PORTS = "{0,1}"
+# Ex. 10 Gbps: TRAFFICGEN_MOONGEN_LINE_SPEED_GBPS = '10'
+# Today only 10 Gbps is supported
+TRAFFICGEN_MOONGEN_LINE_SPEED_GBPS = '10'
# MoonGen Configuration and Connection Info-- END
###################################################
diff --git a/docs/configguide/installation.rst b/docs/configguide/installation.rst
index c426dcea..70572b07 100755
--- a/docs/configguide/installation.rst
+++ b/docs/configguide/installation.rst
@@ -42,6 +42,12 @@ download at OPNFV website.
vloop-vnf changelog:
====================
+* `vloop-vnf-ubuntu-14.04_20160804`_
+
+ * Linux kernel 4.4.0 installed
+ * libnuma-dev installed
+ * security updates applied
+
* `vloop-vnf-ubuntu-14.04_20160303`_
* snmpd service is disabled by default to avoid error messages during VM boot
@@ -144,6 +150,7 @@ running any of the above. For example:
.. _a link: http://www.softwarecollections.org/en/scls/rhscl/python33/
.. _virtualenv: https://virtualenv.readthedocs.org/en/latest/
+.. _vloop-vnf-ubuntu-14.04_20160804: http://artifacts.opnfv.org/vswitchperf/vnf/vloop-vnf-ubuntu-14.04_20160804.qcow2
.. _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
@@ -179,9 +186,19 @@ 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
+seen above, the configuration will need 10 hugepages total to run all tests
within vsperf if the pagesize is set correctly to 1GB.
+VSPerf will verify hugepage amounts are free before executing test
+environments. In case of hugepage amounts not being free, test initialization
+will fail and testing will stop.
+
+**Please Note**: In some instances on a test failure dpdk resources may not
+release hugepages used in dpdk configuration. It is recommended to configure a
+few extra hugepages to prevent a false detection by VSPerf that not enough free
+hugepages are available to execute the test environment. Normally dpdk would use
+previously allocated hugepages upon initialization.
+
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.
@@ -194,3 +211,8 @@ You can review your hugepage amounts by executing the following command
.. code:: bash
cat /proc/meminfo | grep Huge
+
+If no hugepages are available vsperf will try to automatically allocate some.
+Allocation is controlled by HUGEPAGE_RAM_ALLOCATION configuration parameter in
+``02_vswitch.conf`` file. Default is 2GB, resulting in either 2 1GB hugepages
+or 1024 2MB hugepages.
diff --git a/docs/configguide/trafficgen.rst b/docs/configguide/trafficgen.rst
index 798248ac..939b6cad 100644
--- a/docs/configguide/trafficgen.rst
+++ b/docs/configguide/trafficgen.rst
@@ -385,6 +385,8 @@ can be found here:
https://github.com/emmericp/MoonGen
+* Note: Today, MoonGen with VSPERF only supports 10Gbps line speeds.
+
For VSPerf use, MoonGen should be cloned from here (as opposed to the afore
mentioned GitHub):
diff --git a/docs/userguide/testusage.rst b/docs/userguide/testusage.rst
index d807590d..b5f47998 100755
--- a/docs/userguide/testusage.rst
+++ b/docs/userguide/testusage.rst
@@ -396,7 +396,7 @@ Execution of test with PCI passthrough with vswitch disabled:
.. code-block:: console
$ ./vsperf --conf-file=<path_to_custom_conf>/10_custom.conf
- --vswtich none --vnf QemuPciPassthrough pvp_tput
+ --vswitch none --vnf QemuPciPassthrough pvp_tput
Any of supported guest-loopback-application_ can be used inside VM with
PCI passthrough support.
@@ -526,7 +526,10 @@ for selected Packet Forwarder:
# testpmd configuration
TESTPMD_ARGS = []
- # packet forwarding mode: io|mac|mac_retry|macswap|flowgen|rxonly|txonly|csum|icmpecho
+ # packet forwarding mode supported by testpmd; Please see DPDK documentation
+ # for comprehensive list of modes supported by your version.
+ # e.g. io|mac|mac_retry|macswap|flowgen|rxonly|txonly|csum|icmpecho|...
+ # Note: Option "mac_retry" has been changed to "mac retry" since DPDK v16.07
TESTPMD_FWD_MODE = 'csum'
# checksum calculation layer: ip|udp|tcp|sctp|outer-ip
TESTPMD_CSUM_LAYER = 'ip'
diff --git a/systems/centos/build_base_machine.sh b/systems/centos/build_base_machine.sh
index d3ac3e2b..d94dc975 100755
--- a/systems/centos/build_base_machine.sh
+++ b/systems/centos/build_base_machine.sh
@@ -58,6 +58,8 @@ zlib-devel
glib2-devel
pixman-devel
socat
+numactl
+numactl-devel
# install gvim
vim-X11
diff --git a/systems/fedora/20/build_base_machine.sh b/systems/fedora/20/build_base_machine.sh
index 96bb17df..839d2bee 100755
--- a/systems/fedora/20/build_base_machine.sh
+++ b/systems/fedora/20/build_base_machine.sh
@@ -62,6 +62,10 @@ libreport-python3
abrt-python3
abrt-addon-python3
+# libs
+numactl
+numactl-devel
+
# install git-review tool
git-review
-" | grep -v ^#) \ No newline at end of file
+" | grep -v ^#)
diff --git a/systems/fedora/21/build_base_machine.sh b/systems/fedora/21/build_base_machine.sh
index 69b067f9..e4969893 100755
--- a/systems/fedora/21/build_base_machine.sh
+++ b/systems/fedora/21/build_base_machine.sh
@@ -65,6 +65,10 @@ libreport-python3
abrt-python3
abrt-addon-python3
+# libs
+numactl
+numactl-devel
+
# install git-review tool
git-review
" | grep -v ^#) || exit 1
diff --git a/systems/fedora/22/build_base_machine.sh b/systems/fedora/22/build_base_machine.sh
index 0ca565f3..3cfe0c78 100755
--- a/systems/fedora/22/build_base_machine.sh
+++ b/systems/fedora/22/build_base_machine.sh
@@ -66,9 +66,13 @@ libreport-python3
abrt-python3
abrt-addon-python3
+# libs
+numactl
+numactl-devel
+
# install git-review tool
git-review
" | grep -v ^#)
# Create hugepage dirs
-mkdir -p /dev/hugepages \ No newline at end of file
+mkdir -p /dev/hugepages
diff --git a/systems/rhel/7.2/build_base_machine.sh b/systems/rhel/7.2/build_base_machine.sh
index 86608066..2319535b 100755
--- a/systems/rhel/7.2/build_base_machine.sh
+++ b/systems/rhel/7.2/build_base_machine.sh
@@ -50,6 +50,8 @@ pkglist=(
socat\
tk-devel\
wget\
+ numactl\
+ numactl-devel\
)
# python tools for proper QEMU, DPDK, and OVS make
@@ -95,4 +97,4 @@ rm -f Python-3.4.2.tar.xz
pip3.4 install virtualenv
# Create hugepage dirs
-mkdir -p /dev/hugepages \ No newline at end of file
+mkdir -p /dev/hugepages
diff --git a/systems/ubuntu/14.04/build_base_machine.sh b/systems/ubuntu/14.04/build_base_machine.sh
index 9fa8511c..04f4a7e1 100755
--- a/systems/ubuntu/14.04/build_base_machine.sh
+++ b/systems/ubuntu/14.04/build_base_machine.sh
@@ -77,6 +77,10 @@ python3-tk
libpython3.4
python3-reportlab
+# libs
+libnuma1
+libnuma-dev
+
# install git-review tool
git-review
" | grep -v ^#)
diff --git a/systems/ubuntu/build_base_machine.sh b/systems/ubuntu/build_base_machine.sh
index a2b48a26..1b42a790 100755
--- a/systems/ubuntu/build_base_machine.sh
+++ b/systems/ubuntu/build_base_machine.sh
@@ -44,6 +44,8 @@ apt-get -y install autoconf libtool
apt-get -y install libpcap-dev
apt-get -y install libglib2.0
apt-get -y install libfuse-dev
+apt-get -y install libnuma1
+apt-get -y install libnuma-dev
# Some useful tools you may optionally install
#apt-get -y install ctags
diff --git a/testcases/testcase.py b/testcases/testcase.py
index 5f5c9358..d88840d7 100644
--- a/testcases/testcase.py
+++ b/testcases/testcase.py
@@ -14,14 +14,18 @@
"""TestCase base class
"""
+from collections import OrderedDict
+import copy
import csv
+import logging
+import math
import os
+import re
import time
-import logging
import subprocess
-import copy
-from collections import OrderedDict
+from conf import settings as S
+from conf import get_test_param
import core.component_factory as component_factory
from core.loader import Loader
from core.results.results_constants import ResultsConstants
@@ -29,8 +33,7 @@ from tools import tasks
from tools import hugepages
from tools import functions
from tools.pkt_gen.trafficgen.trafficgenhelper import TRAFFIC_DEFAULTS
-from conf import settings as S
-from conf import get_test_param
+
class TestCase(object):
"""TestCase base class
@@ -189,6 +192,10 @@ class TestCase(object):
# mount hugepages if needed
self._mount_hugepages()
+ # verify enough hugepages are free to run the testcase
+ if not self._check_for_enough_hugepages():
+ raise RuntimeError('Not enough hugepages free to run test.')
+
# copy sources of l2 forwarding tools into VM shared dir if needed
self._copy_fwd_tools_for_all_guests()
@@ -391,7 +398,6 @@ class TestCase(object):
except subprocess.CalledProcessError:
self._logger.error('Unable to copy DPDK and l2fwd to shared directory')
-
def _mount_hugepages(self):
"""Mount hugepages if usage of DPDK or Qemu is detected
"""
@@ -411,6 +417,80 @@ class TestCase(object):
hugepages.umount_hugepages()
self._hugepages_mounted = False
+ def _check_for_enough_hugepages(self):
+ """Check to make sure enough hugepages are free to satisfy the
+ test environment.
+ """
+ hugepages_needed = 0
+ hugepage_size = hugepages.get_hugepage_size()
+ # get hugepage amounts per guest
+ for guest in range(self.deployment.count('v')):
+ hugepages_needed += math.ceil((int(S.getValue(
+ 'GUEST_MEMORY')[guest]) * 1000) / hugepage_size)
+
+ # get hugepage amounts for each socket on dpdk
+ sock0_mem, sock1_mem = 0, 0
+ if S.getValue('VSWITCH').lower().count('dpdk'):
+ # the import below needs to remain here and not put into the module
+ # imports because of an exception due to settings not yet loaded
+ from vswitches import ovs_dpdk_vhost
+ if ovs_dpdk_vhost.OvsDpdkVhost.old_dpdk_config():
+ match = re.search(
+ '-socket-mem\s+(\d+),(\d+)',
+ ''.join(S.getValue('VSWITCHD_DPDK_ARGS')))
+ if match:
+ sock0_mem, sock1_mem = (int(match.group(1)) / 1024,
+ int(match.group(2)) / 1024)
+ else:
+ logging.info(
+ 'Could not parse socket memory config in dpdk params.')
+ else:
+ sock0_mem, sock1_mem = (
+ S.getValue(
+ 'VSWITCHD_DPDK_CONFIG')['dpdk-socket-mem'].split(','))
+ sock0_mem, sock1_mem = (int(sock0_mem) / 1024,
+ int(sock1_mem) / 1024)
+
+ # If hugepages needed, verify the amounts are free
+ if any([hugepages_needed, sock0_mem, sock1_mem]):
+ free_hugepages = hugepages.get_free_hugepages()
+ if hugepages_needed:
+ logging.info('Need %s hugepages free for guests',
+ hugepages_needed)
+ result1 = free_hugepages >= hugepages_needed
+ free_hugepages -= hugepages_needed
+ else:
+ result1 = True
+
+ if sock0_mem:
+ logging.info('Need %s hugepages free for dpdk socket 0',
+ sock0_mem)
+ result2 = hugepages.get_free_hugepages('0') >= sock0_mem
+ free_hugepages -= sock0_mem
+ else:
+ result2 = True
+
+ if sock1_mem:
+ logging.info('Need %s hugepages free for dpdk socket 1',
+ sock1_mem)
+ result3 = hugepages.get_free_hugepages('1') >= sock1_mem
+ free_hugepages -= sock1_mem
+ else:
+ result3 = True
+
+ logging.info('Need a total of {} total hugepages'.format(
+ hugepages_needed + sock1_mem + sock0_mem))
+
+ # The only drawback here is sometimes dpdk doesn't release
+ # its hugepages on a test failure. This could cause a test
+ # to fail when dpdk would be OK to start because it will just
+ # use the previously allocated hugepages.
+ result4 = True if free_hugepages >= 0 else False
+
+ return all([result1, result2, result3, result4])
+ else:
+ return True
+
@staticmethod
def write_result_to_file(results, output):
"""Write list of dictionaries to a CSV file.
diff --git a/tools/hugepages.py b/tools/hugepages.py
index 3a434d6e..02e4f29c 100644
--- a/tools/hugepages.py
+++ b/tools/hugepages.py
@@ -20,6 +20,7 @@ import re
import subprocess
import logging
import locale
+import math
from tools import tasks
from conf import settings
@@ -31,29 +32,105 @@ _LOGGER = logging.getLogger(__name__)
#
+def get_hugepage_size():
+ """Return the size of the configured hugepages
+ """
+ hugepage_size_re = re.compile(r'^Hugepagesize:\s+(?P<size_hp>\d+)\s+kB',
+ re.IGNORECASE)
+ with open('/proc/meminfo', 'r') as fh:
+ data = fh.readlines()
+ for line in data:
+ match = hugepage_size_re.search(line)
+ if match:
+ _LOGGER.info('Hugepages size: %s', match.group('size_hp'))
+ return int(match.group('size_hp'))
+ else:
+ _LOGGER.error('Could not parse for hugepage size')
+ return 0
+
+
+def allocate_hugepages():
+ """Allocate hugepages on the fly
+ """
+ hp_size = get_hugepage_size()
+
+ if hp_size > 0:
+ nr_hp = int(math.ceil(settings.getValue('HUGEPAGE_RAM_ALLOCATION')/hp_size))
+ _LOGGER.info('Will allocate %s hugepages.', nr_hp)
+
+ nr_hugepages = 'vm.nr_hugepages=' + str(nr_hp)
+ try:
+ tasks.run_task(['sudo', 'sysctl', nr_hugepages],
+ _LOGGER, 'Trying to allocate hugepages..', True)
+ except subprocess.CalledProcessError:
+ _LOGGER.error('Unable to allocate hugepages.')
+ return False
+ return True
+
+ else:
+ _LOGGER.error('Division by 0 will be supported in next release')
+ return False
+
+
+def get_free_hugepages(socket=None):
+ """Get the free hugepage totals on the system.
+
+ :param socket: optional socket param to get free hugepages on a socket. To
+ be passed a string.
+ :returns: hugepage amount as int
+ """
+ hugepage_free_re = re.compile(r'HugePages_Free:\s+(?P<free_hp>\d+)$')
+ if socket:
+ if os.path.exists(
+ '/sys/devices/system/node/node{}/meminfo'.format(socket)):
+ meminfo_path = '/sys/devices/system/node/node{}/meminfo'.format(
+ socket)
+ else:
+ _LOGGER.info('No hugepage info found for socket {}'.format(socket))
+ return 0
+ else:
+ meminfo_path = '/proc/meminfo'
+
+ with open(meminfo_path, 'r') as fh:
+ data = fh.readlines()
+ for line in data:
+ match = hugepage_free_re.search(line)
+ if match:
+ _LOGGER.info('Hugepages free: %s %s', match.group('free_hp'),
+ 'on socket {}'.format(socket) if socket else '')
+ return int(match.group('free_hp'))
+ else:
+ _LOGGER.info('Could not parse for hugepage size')
+ return 0
+
+
def is_hugepage_available():
- """Check if hugepages are available on the system.
+ """Check if hugepages are configured/available on the system.
"""
- hugepage_re = re.compile(r'^HugePages_Free:\s+(?P<num_hp>\d+)$')
+ hugepage_size_re = re.compile(r'^Hugepagesize:\s+(?P<size_hp>\d+)\s+kB',
+ re.IGNORECASE)
# read in meminfo
with open('/proc/meminfo') as mem_file:
mem_info = mem_file.readlines()
- # first check if module is loaded
+ # see if the hugepage size is the recommended value
for line in mem_info:
- result = hugepage_re.match(line)
- if not result:
- continue
-
- num_huge = result.group('num_hp')
- if not num_huge:
- _LOGGER.info('No free hugepages.')
- else:
- _LOGGER.info('Found \'%s\' free hugepage(s).', num_huge)
- return True
-
- return False
+ match_size = hugepage_size_re.match(line)
+ if match_size:
+ if match_size.group('size_hp') != '1048576':
+ _LOGGER.info(
+ '%s%s%s kB',
+ 'Hugepages not configured for recommend 1GB size. ',
+ 'Currently set at ', match_size.group('size_hp'))
+ num_huge = get_free_hugepages()
+ if num_huge == 0:
+ _LOGGER.info('No free hugepages.')
+ if not allocate_hugepages():
+ return False
+ else:
+ _LOGGER.info('Found \'%s\' free hugepage(s).', num_huge)
+ return True
def is_hugepage_mounted():
@@ -69,10 +146,11 @@ def is_hugepage_mounted():
def mount_hugepages():
- """Ensure hugepages are mounted.
+ """Ensure hugepages are mounted. Raises RuntimeError if no configured
+ hugepages are available.
"""
if not is_hugepage_available():
- return
+ raise RuntimeError('No Hugepages configured.')
if is_hugepage_mounted():
return
diff --git a/tools/namespace.py b/tools/namespace.py
index e6bcd819..9131398f 100644
--- a/tools/namespace.py
+++ b/tools/namespace.py
@@ -108,8 +108,8 @@ def get_system_namespace_list():
Return tuple of strings for namespaces on the system
:return: tuple of namespaces as string
"""
- return tuple(os.listdir('/var/run/netns'))
-
+ return tuple(os.listdir('/var/run/netns')) if os.path.exists(
+ '/var/run/netns') else tuple()
def get_vsperf_namespace_list():
"""
diff --git a/tools/pkt_gen/moongen/moongen.py b/tools/pkt_gen/moongen/moongen.py
index 47f288a4..86a39a77 100644
--- a/tools/pkt_gen/moongen/moongen.py
+++ b/tools/pkt_gen/moongen/moongen.py
@@ -20,10 +20,11 @@ Moongen Traffic Generator Model
"""
# python imports
-import logging
from collections import OrderedDict
-import subprocess
+import logging
+import math
import re
+import subprocess
# VSPerf imports
from conf import settings
@@ -49,6 +50,13 @@ class Moongen(ITrafficGenerator):
self._moongen_user = settings.getValue('TRAFFICGEN_MOONGEN_USER')
self._moongen_ports = settings.getValue('TRAFFICGEN_MOONGEN_PORTS')
+ if settings.getValue('TRAFFICGEN_MOONGEN_LINE_SPEED_GBPS') == '10':
+ self._moongen_line_speed = math.pow(10, 10)
+ else:
+ raise RuntimeError(
+ 'MOONGEN: Invalid line speed in configuration ' + \
+ 'file (today 10Gbps supported)')
+
@property
def traffic_defaults(self):
"""Default traffic values.
@@ -157,10 +165,17 @@ class Moongen(ITrafficGenerator):
if one_shot:
out_file.write("oneShot = true,\n")
- # Assume 10G line rates at the moment. Need to convert VSPERF
- # frame_rate (percentage of line rate) to Mpps for Moongen
+ # Need to convert VSPERF frame_rate (percentage of line rate)
+ # to Mpps for Moongen
+ start_rate = str(
+ (traffic['frame_rate'] / 100) * (self._moongen_line_speed / \
+ (8 * (traffic['l2']['framesize'] + 20)) / math.pow(10, 6)))
+
+ logging.debug("startRate = " + start_rate)
+
+ out_file.write("startRate = " + \
+ start_rate + "\n")
- out_file.write("startRate = " + str((traffic['frame_rate'] / 100) * 14.88) + "\n")
out_file.write("}" + "\n")
out_file.close()
@@ -473,10 +488,21 @@ class Moongen(ITrafficGenerator):
'PARAMETERS section of Moongen log file')
frame_size = 0
- if results_match and parameters_match:
+ # Each packet stream in the MoonGen report is prefaced with the
+ # words '[REPORT]Device'. Count the instances of this string to
+ # get the total aggregrate throughput. For example:
+ #
+ # - If num_traffic_streams = 1, there is a single
+ # unidirectional stream
+ #
+ # - If num_traffic_streams = 2, there is a bidirectional
+ # traffic stream
+ num_traffic_streams = mytext.count('[REPORT]Device')
+
+ if results_match and parameters_match and num_traffic_streams:
# Assume for now 10G link speed
- max_theoretical_mfps = (
- (10000000000 / 8) / (frame_size + 20))
+ max_theoretical_fps = (
+ num_traffic_streams * (10000000000 / 8) / (frame_size + 20))
moongen_results[ResultsConstants.THROUGHPUT_RX_FPS] = (
float(results_match.group(6)) * 1000000)
@@ -485,8 +511,7 @@ class Moongen(ITrafficGenerator):
(float(results_match.group(6)) * frame_size + 20) * 8)
moongen_results[ResultsConstants.THROUGHPUT_RX_PERCENT] = (
- float(results_match.group(6)) * \
- 1000000 / max_theoretical_mfps * 100)
+ (100 * float(results_match.group(6)) * 1000000) / max_theoretical_fps)
moongen_results[ResultsConstants.TX_RATE_FPS] = (
float(results_match.group(5)) * 1000000)
@@ -495,8 +520,7 @@ class Moongen(ITrafficGenerator):
float(results_match.group(5)) * (frame_size + 20) * 8)
moongen_results[ResultsConstants.TX_RATE_PERCENT] = (
- float(results_match.group(5)) *
- 1000000 / max_theoretical_mfps * 100)
+ (100 * float(results_match.group(5)) * 1000000) / max_theoretical_fps)
moongen_results[ResultsConstants.B2B_TX_COUNT] = (
float(results_match.group(1)))
diff --git a/tools/pkt_gen/xena/XenaDriver.py b/tools/pkt_gen/xena/XenaDriver.py
index aa8443c9..d3862312 100644
--- a/tools/pkt_gen/xena/XenaDriver.py
+++ b/tools/pkt_gen/xena/XenaDriver.py
@@ -1001,9 +1001,21 @@ class XenaTXStats(object):
mydict = statdict
return mydict
-
def aggregate_stats(stat1, stat2):
"""
+ Judge whether stat1 and stat2 both have same key, if both have same key,
+ call the aggregate fuction, else use the stat1's value
+ """
+ newstat = dict()
+ for keys in stat1.keys():
+ if keys in stat2 and isinstance(stat1[keys], dict):
+ newstat[keys] = aggregate(stat1[keys], stat2[keys])
+ else:
+ newstat[keys] = stat1[keys]
+ return newstat
+
+def aggregate(stat1, stat2):
+ """
Recursive function to aggregate two sets of statistics. This is used when
bi directional traffic is done and statistics need to be calculated based
on two sets of statistics.
@@ -1014,7 +1026,7 @@ def aggregate_stats(stat1, stat2):
newstat = dict()
for (keys1, keys2) in zip(stat1.keys(), stat2.keys()):
if isinstance(stat1[keys1], dict):
- newstat[keys1] = aggregate_stats(stat1[keys1], stat2[keys2])
+ newstat[keys1] = aggregate(stat1[keys1], stat2[keys2])
else:
if not isinstance(stat1[keys1], int) and not isinstance(
[keys1], float):
diff --git a/vnfs/qemu/qemu_pci_passthrough.py b/vnfs/qemu/qemu_pci_passthrough.py
index 14810f0a..951d6086 100644
--- a/vnfs/qemu/qemu_pci_passthrough.py
+++ b/vnfs/qemu/qemu_pci_passthrough.py
@@ -44,8 +44,8 @@ class QemuPciPassthrough(IVnfQemu):
# in case of SRIOV and PCI passthrough we must ensure, that MAC addresses are swapped
if S.getValue('SRIOV_ENABLED') and not self._testpmd_fwd_mode.startswith('mac'):
self._logger.info("SRIOV detected, forwarding mode of testpmd was changed from '%s' to '%s'",
- self._testpmd_fwd_mode, 'mac_retry')
- self._testpmd_fwd_mode = 'mac_retry'
+ self._testpmd_fwd_mode, 'mac')
+ self._testpmd_fwd_mode = 'mac'
for nic in self._nics:
self._cmd += ['-device', 'vfio-pci,host=' + nic['pci']]
diff --git a/vsperf b/vsperf
index 700539c9..1f693a55 100755
--- a/vsperf
+++ b/vsperf
@@ -557,13 +557,13 @@ def main():
_LOGGER.error("Cannot specify tests with both positional args and --test.")
sys.exit(1)
- # sriov handling
- settings.setValue('SRIOV_ENABLED', enable_sriov(settings.getValue('WHITELIST_NICS')))
-
# modify NIC configuration to decode enhanced PCI IDs
wl_nics_orig = list(networkcard.check_pci(pci) for pci in settings.getValue('WHITELIST_NICS'))
settings.setValue('WHITELIST_NICS_ORIG', wl_nics_orig)
+ # sriov handling is performed on checked/expanded PCI IDs
+ settings.setValue('SRIOV_ENABLED', enable_sriov(wl_nics_orig))
+
nic_list = []
for nic in wl_nics_orig:
tmp_nic = networkcard.get_nic_info(nic)