diff options
111 files changed, 2062 insertions, 856 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 91dc6d25..1aa61085 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,8 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + # General Coding Style ## Code @@ -1,13 +1,13 @@ -Copyright 2015 Open Platform for NFV Project, Inc. and its contributors - - 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. +Copyright 2015-2017 Open Platform for NFV Project, Inc. and its contributors + +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. @@ -1,3 +1,8 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + # VSPERF - vSwitch Performance Tests Documentation for this project including the [installation userguide] is contained @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright 2015 Intel Corporation. +# Copyright 2017 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,9 +19,10 @@ PYLINT="pylint" PYLINT_RC='pylintrc' PYLINT_RATING_GATE="10" -FILE_REGEX="(vsperf|.*\.py)" -FIND_OPTIONS="-regextype posix-egrep -iregex (./)?$FILE_REGEX" +PYLINT_RATING_MIN=$PYLINT_RATING_GATE +FILE_REGEX="(^vsperf|\.py)$" FILE_LIST="/tmp/vsperf_check_list.txt" +BC=`which bc` # print usage if requested function usage() { @@ -39,8 +40,10 @@ Otherwise gained pylint rating will be displayed. -h, --help Script usage + -b, --black Suppress colours. Output will be black&white. -m, --modified Script will check python files, which have been modified within current repository. + Examples: ./check @@ -64,9 +67,27 @@ EOM # compare pylint result with predefined gate function rating_is_ok() { # bc is not part of basic Centos installation - # so let us do integer comparison only - int_rating=`echo $1 | sed -e 's/\..*$//'` - [ $int_rating -ge $PYLINT_RATING_GATE ] + # so let us check if it is available + if [ "x$BC" == "x" ] ; then + # no bc, so do integer comparison only + int_rating=`echo $1 | sed -e 's/\..*$//'` + int_rating_min=`echo $PYLINT_RATING_MIN | sed -e 's/\..*$//'` + [ $int_rating -lt $int_rating_min ] && PYLINT_RATING_MIN=$int_rating + if [ $int_rating -lt $PYLINT_RATING_GATE ] ; then + return 1 + else + return 0 + fi + else + if (( $(echo "$1<$PYLINT_RATING_MIN" | bc -l) )) ; then + PYLINT_RATING_MIN=$1 + fi + if (( $(echo "$1<$PYLINT_RATING_GATE" | bc -l) )) ; then + return 1 + else + return 0 + fi + fi } ##### MAIN ##### @@ -76,6 +97,19 @@ if [ "x$1" == "x-h" -o "x$1" == "x--help" ] ; then exit 0 fi +# set colours +if [ "x$1" == "x-b" -o "x$1" == "x--black" ] ; then + shift + RED="" + GREEN="" + BLACK="" +else + RED="\e[31m" + GREEN="\e[32m" + BLACK="\e[0m" +fi + + # check if pylint is available if ! which $PYLINT &>/dev/null ; then echo "$PYLINT is not available, thus check can't be executed" @@ -95,14 +129,14 @@ EXCLUDED_MODULES=`grep "^ *EXCLUDE_MODULES" conf/00_common.conf | tr '"' "'"` rm $FILE_LIST &> /dev/null if [ "x$1" == "x-m" -o "x$1" == "x--modified" ] ; then # check of modified files requested - git status --porcelain | cut -b4- | egrep -i "^${FILE_REGEX}$" > $FILE_LIST + git status --porcelain | cut -b4- | egrep -i "${FILE_REGEX}" | sort > $FILE_LIST elif [ "x$*" == "x" ] ; then # list is empty, check all python files - find . -type f $FIND_OPTIONS > $FILE_LIST + git ls-tree --name-only -r HEAD | egrep -i "${FILE_REGEX}" | sort > $FILE_LIST else for item in $* ; do if [ -d $item ] ; then - find $item -type f $FIND_OPTIONS >> $FILE_LIST + git ls-tree --name-only -r HEAD $item | egrep -i "${FILE_REGEX}" | sort >> $FILE_LIST elif [ -f $item ] ; then echo $item >> $FILE_LIST else @@ -113,22 +147,26 @@ else fi # check if there is anything to check +echo "Execution of pylint checks:" if [ -s $FILE_LIST ] ; then for pyfile in `cat $FILE_LIST | sort` ; do # get base name pyfile_basename="'"`basename $pyfile .py`"'" # and check if it should be excluded or not if ( echo $EXCLUDED_MODULES | grep -w $pyfile_basename > /dev/null ) ; then - printf "%-70s \e[32m%-6s\e[0m\n" $pyfile "EXCLUDED" + printf " %-70s %-6s\n" $pyfile "EXCLUDED" continue fi # run pylint and extract final rating rating=`$PYLINT --rcfile $PYLINT_RC $pyfile 2>/dev/null | tail -n3 | grep rated | sed -e 's/^.*rated at \([0-9.]*\).*$/\1/'` # evaluate and display aquired rating - if rating_is_ok $rating ; then - printf "%-70s \e[32m%-6s\e[0m\n" $pyfile "OK" + if [ "x$rating" == "x" ] ; then + # rating is not available for files without python statements + printf " %-70s %-6s\n" $pyfile "NA" + elif rating_is_ok $rating ; then + printf " %-70s ${GREEN}%-6s${BLACK}\n" $pyfile "OK" else - printf "%-70s \e[31m%-6s\e[0m\n" $pyfile $rating + printf " %-70s ${RED}%-6s${BLACK}\n" $pyfile $rating fi done else @@ -139,5 +177,10 @@ fi # clean up rm $FILE_LIST &> /dev/null -exit 0 +if [ "$PYLINT_RATING_MIN" != "$PYLINT_RATING_GATE" ] ; then + echo -e "Pylint check has failed. All files must have score ${PYLINT_RATING_GATE}.\n" + exit 1 +else + exit 0 +fi ##### MAIN end ##### diff --git a/ci/build-vsperf.sh b/ci/build-vsperf.sh index 24fbb8fa..b4a0f24b 100755 --- a/ci/build-vsperf.sh +++ b/ci/build-vsperf.sh @@ -27,8 +27,9 @@ EXIT=0 EXIT_TC_FAILED=1 EXIT_SANITY_TC_FAILED=2 -EXIT_NO_RESULTS=10 -EXIT_NO_TEST_REPORT_LOG_DIR=11 +EXIT_PYLINT_FAILED=4 +EXIT_NO_RESULTS=128 +EXIT_NO_TEST_REPORT_LOG_DIR=256 # # configuration @@ -50,6 +51,8 @@ TESTPARAM_MERGE="--integration" # DAILY - run selected TCs for defined packet sizes TESTCASES_DAILY='phy2phy_tput back2back phy2phy_tput_mod_vlan phy2phy_scalability pvp_tput pvp_back2back pvvp_tput pvvp_back2back' TESTPARAM_DAILY='--test-params TRAFFICGEN_PKT_SIZES=(64,128,512,1024,1518)' +TESTCASES_SRIOV='pvp_tput' +TESTPARAM_SRIOV='--test-params TRAFFICGEN_PKT_SIZES=(64,128,512,1024,1518)' # check if user config file exists if not then we will use default settings if [ -f $HOME/vsperf-${BRANCH}.conf ] ; then # branch specific config was found @@ -61,6 +64,12 @@ else CONF_FILE="" fi fi +# check if sriov specific config file exists if not then use default configuration +if [ -f $HOME/vsperf-${BRANCH}.conf.sriov ] ; then + CONF_FILE_SRIOV="${CONF_FILE}.sriov" +else + CONF_FILE_SRIOV=$CONF_FILE +fi # Test report related configuration TEST_REPORT_PARTIAL="*_test_report.rst" @@ -157,6 +166,17 @@ function execute_vsperf() { DATE_SUFFIX=$(date -u +"%Y-%m-%d_%H-%M-%S") case $1 in + "SRIOV") + # use SRIOV specific TCs and configuration + TESTPARAM=$TESTPARAM_SRIOV + TESTCASES=$TESTCASES_SRIOV + # figure out log file name + LOG_SUBDIR="SRIOV" + LOG_FILE="${LOG_FILE_PREFIX}_${LOG_SUBDIR}_${DATE_SUFFIX}.log" + + echo " $VSPERF_BIN --vswitch none --vnf QemuPciPassthrough $CONF_FILE_SRIOV $TESTPARAM $TESTCASES &> $LOG_FILE" + $VSPERF_BIN --vswitch none --vnf QemuPciPassthrough $CONF_FILE_SRIOV $TESTPARAM $TESTCASES &> $LOG_FILE + ;; "OVS_vanilla") # figure out log file name LOG_SUBDIR="OvsVanilla" @@ -188,7 +208,7 @@ function execute_vsperf() { exit $EXIT_NO_RESULTS else print_results "${RES_DIR}" - if [ "$EXIT" -eq "$EXIT_TC_FAILED" ] ; then + if [ $(($EXIT & $EXIT_TC_FAILED)) -gt 0 ] ; then echo "-------------------------------------------------------------------" cat $LOG_FILE echo "-------------------------------------------------------------------" @@ -308,20 +328,28 @@ function execute_vsperf_sanity() { echo >> $LOG_FILE done echo "Sanity log file $LOG_FILE" - if [ "$EXIT" -ne "0" ] ; then + if [ $(($EXIT & $EXIT_SANITY_TC_FAILED)) -gt 0 ] ; then echo "-------------------------------------------------------------------" cat $LOG_FILE echo "-------------------------------------------------------------------" fi } +# execute pylint to check code quality +function execute_vsperf_pylint_check() { + if ! ./check -b ; then + EXIT=$EXIT_PYLINT_FAILED + fi +} + # check and install required packages at nodes running VERIFY and MERGE jobs function dependencies_check() { . /etc/os-release if [ $ID == "ubuntu" ] ; then echo "Dependencies check" echo "==================" - for PACKAGE in "python3-tk" "sysstat" ; do + # install system packages + for PACKAGE in "python3-tk" "sysstat" "bc" ; do if dpkg -s $PACKAGE &> /dev/null ; then printf " %-70s %-6s\n" $PACKAGE "OK" else @@ -329,6 +357,15 @@ function dependencies_check() { sudo apt-get install -y $PACKAGE fi done + # install additional python packages into python environment + for PACKAGE in "pylint" ; do + if pip show $PACKAGE &> /dev/null ; then + printf " %-70s %-6s\n" $PACKAGE "OK" + else + printf " %-70s %-6s\n" $PACKAGE "missing" + pip install $PACKAGE + fi + done echo fi } @@ -386,6 +423,7 @@ case $1 in echo "VSPERF verify job" echo "=================" + execute_vsperf_pylint_check terminate_vsperf execute_vsperf_sanity terminate_vsperf @@ -400,6 +438,7 @@ case $1 in echo "VSPERF merge job" echo "================" + execute_pylint_check terminate_vsperf execute_vsperf_sanity terminate_vsperf @@ -419,6 +458,8 @@ case $1 in terminate_vsperf execute_vsperf OVS_vanilla $1 terminate_vsperf + execute_vsperf SRIOV $1 + terminate_vsperf generate_report diff --git a/conf/01_testcases.conf b/conf/01_testcases.conf index bdaeb4da..4851b043 100755 --- a/conf/01_testcases.conf +++ b/conf/01_testcases.conf @@ -78,6 +78,85 @@ # "Test Modifier": [FrameMod|Other], # "Dependency": [Test_Case_Name |None], +# +# VPP specific macros used in TC defintions +# +VPP_P2P = [ + ['vswitch', 'add_switch', 'int_br0'], # STEP 0 + ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1 + ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2 + ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]', True], + ['vswitch', 'add_connection', 'int_br0', '#STEP[2][0]', '#STEP[1][0]', True], + ['trafficgen', 'send_traffic', {}], + ['vswitch', 'dump_connections', 'int_br0'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]', True], + ['vswitch', 'del_connection', 'int_br0', '#STEP[2][0]', '#STEP[1][0]', True], + ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'], + ['vswitch', 'del_switch', 'int_br0'], + ] +VPP_PVP = [ + ['vswitch', 'add_switch', 'int_br0'], # STEP 0 + ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1 + ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2 + ['vswitch', 'add_vport', 'int_br0'], # STEP 3 + ['vswitch', 'add_vport', 'int_br0'], # STEP 4 + ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]', True], + ['vswitch', 'add_connection', 'int_br0', '#STEP[4][0]', '#STEP[2][0]', True], + ['vswitch', 'add_connection', 'int_br0', '#STEP[2][0]', '#STEP[4][0]', True], + ['vswitch', 'add_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]', True], + ['vnf', 'start'], + ['trafficgen', 'send_traffic', {}], + ['vnf', 'stop'], + ['vswitch', 'dump_connections', 'int_br0'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]', True], + ['vswitch', 'del_connection', 'int_br0', '#STEP[4][0]', '#STEP[2][0]', True], + ['vswitch', 'del_connection', 'int_br0', '#STEP[2][0]', '#STEP[4][0]', True], + ['vswitch', 'del_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]', True], + ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'], + ['vswitch', 'del_switch', 'int_br0'], + ] +VPP_PVVP = [ + ['vswitch', 'add_switch', 'int_br0'], # STEP 0 + ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1 + ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2 + ['vswitch', 'add_vport', 'int_br0'], # STEP 3 + ['vswitch', 'add_vport', 'int_br0'], # STEP 4 + ['vswitch', 'add_vport', 'int_br0'], # STEP 5 + ['vswitch', 'add_vport', 'int_br0'], # STEP 6 + ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]', True], + ['vswitch', 'add_connection', 'int_br0', '#STEP[4][0]', '#STEP[5][0]', True], + ['vswitch', 'add_connection', 'int_br0', '#STEP[6][0]', '#STEP[2][0]', True], + ['vswitch', 'add_connection', 'int_br0', '#STEP[2][0]', '#STEP[6][0]', True], + ['vswitch', 'add_connection', 'int_br0', '#STEP[5][0]', '#STEP[4][0]', True], + ['vswitch', 'add_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]', True], + ['vnf1', 'start'], + ['vnf2', 'start'], + ['trafficgen', 'send_traffic', {}], + ['vnf2', 'stop'], + ['vnf1', 'stop'], + ['vswitch', 'dump_connections', 'int_br0'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]', True], + ['vswitch', 'del_connection', 'int_br0', '#STEP[4][0]', '#STEP[5][0]', True], + ['vswitch', 'del_connection', 'int_br0', '#STEP[6][0]', '#STEP[2][0]', True], + ['vswitch', 'del_connection', 'int_br0', '#STEP[2][0]', '#STEP[6][0]', True], + ['vswitch', 'del_connection', 'int_br0', '#STEP[5][0]', '#STEP[4][0]', True], + ['vswitch', 'del_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]', True], + ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[5][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[6][0]'], + ['vswitch', 'del_switch', 'int_br0'], + ] + +# +# Generic performance TC definitions +# PERFORMANCE_TESTS = [ { "Name": "phy2phy_tput", @@ -95,7 +174,27 @@ PERFORMANCE_TESTS = [ "Description": "LTD.Forwarding.RFC2889.MaxForwardingRate", "Parameters" : { "TRAFFIC" : { - "traffic_type" : "rfc2889", + "traffic_type" : "rfc2889_forwarding", + }, + }, + }, + { + "Name": "phy2phy_learning", + "Deployment": "p2p", + "Description": "LTD.AddrLearning.RFC2889.AddrLearningRate", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2889_learning", + }, + }, + }, + { + "Name": "phy2phy_caching", + "Deployment": "p2p", + "Description": "LTD.AddrCaching.RFC2889.AddrCachingCapacity", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2889_caching", }, }, }, @@ -249,4 +348,113 @@ PERFORMANCE_TESTS = [ }, }, }, + { + "Name": "phy2phy_tput_vpp", + "Deployment": "clean", + "Description": "VPP: LTD.Throughput.RFC2544.PacketLossRatio", + "vSwitch" : "VppDpdkVhost", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_throughput", + }, + }, + "TestSteps": VPP_P2P, + }, + { + "Name": "phy2phy_cont_vpp", + "Deployment": "clean", + "Description": "VPP: Phy2Phy Continuous Stream", + "vSwitch" : "VppDpdkVhost", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_continuous", + "frame_rate" : 100, + }, + }, + "TestSteps": VPP_P2P, + }, + { + "Name": "phy2phy_back2back_vpp", + "Deployment": "clean", + "Description": "VPP: LTD.Throughput.RFC2544.BackToBackFrames", + "vSwitch" : "VppDpdkVhost", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_back2back", + }, + }, + "TestSteps": VPP_P2P, + }, + { + "Name": "pvp_tput_vpp", + "Deployment": "clean", + "Description": "VPP: LTD.Throughput.RFC2544.PacketLossRatio", + "vSwitch" : "VppDpdkVhost", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_throughput", + }, + }, + "TestSteps": VPP_PVP, + }, + { + "Name": "pvp_cont_vpp", + "Deployment": "clean", + "Description": "VPP: PVP Continuous Stream", + "vSwitch" : "VppDpdkVhost", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_continuous", + }, + }, + "TestSteps": VPP_PVP, + }, + { + "Name": "pvp_back2back_vpp", + "Deployment": "clean", + "Description": "VPP: LTD.Throughput.RFC2544.BackToBackFrames", + "vSwitch" : "VppDpdkVhost", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_back2back", + }, + }, + "TestSteps": VPP_PVP, + }, + { + "Name": "pvvp_tput_vpp", + "Deployment": "clean", + "Description": "VPP: LTD.Throughput.RFC2544.PacketLossRatio", + "vSwitch" : "VppDpdkVhost", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_throughput", + }, + }, + "TestSteps": VPP_PVVP, + }, + { + "Name": "pvvp_cont_vpp", + "Deployment": "clean", + "Description": "VPP: PVP Continuous Stream", + "vSwitch" : "VppDpdkVhost", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_continuous", + }, + }, + "TestSteps": VPP_PVVP, + }, + { + "Name": "pvvp_back2back_vpp", + "Deployment": "clean", + "Description": "VPP: LTD.Throughput.RFC2544.BackToBackFrames", + "vSwitch" : "VppDpdkVhost", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_back2back", + }, + }, + "TestSteps": VPP_PVVP, + }, ] diff --git a/conf/02_vswitch.conf b/conf/02_vswitch.conf index 2ca7591c..2bac1732 100644 --- a/conf/02_vswitch.conf +++ b/conf/02_vswitch.conf @@ -33,6 +33,12 @@ RTE_TARGET = 'x86_64-native-linuxapp-gcc' # will be used for testing WHITELIST_NICS = [] +# List defines an amount of memory to be allocated by DPDK at NUMA nodes. This +# option is shared by all vSwitches with DPDK support. In case, that there is +# a socket-mem configuration specified in vSwitch specific configuration option, +# then it will be overridden by DPDK_SOCKET_MEM value. +DPDK_SOCKET_MEM = ['1024', '0'] + # vhost character device file used by dpdkvhostport QemuWrap cases VHOST_DEV_FILE = 'ovs-vhost-net' @@ -103,6 +109,18 @@ PATHS['vswitch'] = { }, 'ovs_var_tmp': '/usr/local/var/run/openvswitch/', 'ovs_etc_tmp': '/usr/local/etc/openvswitch/', + 'VppDpdkVhost': { + 'type' : 'bin', + 'src': { + 'path': os.path.join(ROOT_DIR, 'src/vpp/vpp/build-root/build-vpp-native'), + 'vpp': 'vpp', + 'vppctl': 'vppctl', + }, + 'bin': { + 'vpp': 'vpp', + 'vppctl': 'vppctl', + } + }, } # default OvsVanilla configuration is similar to OvsDpdkVhost except 'path' and 'modules' @@ -116,18 +134,19 @@ PATHS['vswitch']['OvsVanilla']['bin']['modules'] = ['openvswitch'] # ############################ # 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 # This config line is also used for pkt_fwd option (TestPMD phy2phy and pvp tests) -VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4', '--socket-mem 1024,0'] +# NOTE: DPDK socket mem allocation is driven by parameter DPDK_SOCKET_MEM +VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4'] # 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" +# NOTE: DPDK socket mem allocation is driven by parameter DPDK_SOCKET_MEM 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. @@ -169,3 +188,30 @@ LOG_FILE_OVS = 'ovs.log' # default vswitch implementation VSWITCH = "OvsDpdkVhost" + +######################### +## VPP +######################### +# Set of arguments used for startup of VPP +# NOTE: DPDK socket mem allocation is driven by parameter DPDK_SOCKET_MEM +VSWITCH_VPP_ARGS = { + 'unix' : [ + 'interactive', # required by VSPERF to detect successful VPP startup + 'log /tmp/vpp.log', + 'full-coredump', + ], + 'cpu' : [ + 'main-core 3', + 'corelist-workers 4,5', + ], +} + +# log file for VPP +LOG_FILE_VPP = 'vsperf-vpp.log' + +# Select l2 connection method used by VPP. +# Supported values are: 'xconnect', 'l2patch' and 'bridge' +VSWITCH_VPP_L2_CONNECT_MODE = 'xconnect' + +# Options used during creation of dpdkvhostuser interface +VSWITCH_VPP_VHOSTUSER_ARGS = ['feature-mask', '0xFF'] diff --git a/conf/05_collector.conf b/conf/05_collector.conf index bda0ac8d..9fd2558c 100644 --- a/conf/05_collector.conf +++ b/conf/05_collector.conf @@ -20,7 +20,7 @@ COLLECTOR = 'Pidstat' COLLECTOR_DIR = os.path.join(ROOT_DIR, 'tools/collectors') # processes to be monitored by pidstat -PIDSTAT_MONITOR = ['ovs-vswitchd', 'ovsdb-server', 'qemu-system-x86_64'] +PIDSTAT_MONITOR = ['ovs-vswitchd', 'ovsdb-server', 'qemu-system-x86_64', 'vpp'] # options which will be passed to pidstat PIDSTAT_OPTIONS = '-dur' diff --git a/conf/06_pktfwd.conf b/conf/06_pktfwd.conf index 6175aa6a..bb4c1d79 100644 --- a/conf/06_pktfwd.conf +++ b/conf/06_pktfwd.conf @@ -36,4 +36,4 @@ TESTPMD_CSUM_CALC = 'sw' # recognize tunnel headers: on|off TESTPMD_CSUM_PARSE_TUNNEL = 'off' -PIDSTAT_MONITOR = ['ovs-vswitchd', 'ovsdb-server', 'qemu-system-x86_64', 'testpmd'] +PIDSTAT_MONITOR = ['ovs-vswitchd', 'ovsdb-server', 'qemu-system-x86_64', 'vpp', 'testpmd'] diff --git a/core/component_factory.py b/core/component_factory.py index 236a61ed..0256b85c 100644 --- a/core/component_factory.py +++ b/core/component_factory.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -68,6 +68,7 @@ def create_vswitch(deployment_scenario, vswitch_class, traffic, :param tunnel_operation encapsulation/decapsulation or None :return: IVSwitchController for the deployment_scenario """ + # pylint: disable=too-many-return-statements deployment_scenario = deployment_scenario.lower() if deployment_scenario.startswith("p2p"): return VswitchControllerP2P(vswitch_class, traffic) @@ -124,6 +125,7 @@ def create_loadgen(loadgen_type, loadgen_cfg): :param loadgen_class: Reference to load generator class to be used. :return: A new ILoadGenerator class """ + # pylint: disable=too-many-function-args loadgen_type = loadgen_type.lower() if loadgen_type.find("dummy") >= 0: return DummyLoadGen(loadgen_cfg) diff --git a/core/loader/loader.py b/core/loader/loader.py index 0d9c83a6..b0990fa7 100755 --- a/core/loader/loader.py +++ b/core/loader/loader.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,11 +17,11 @@ from conf import settings from core.loader.loader_servant import LoaderServant -from tools.pkt_gen.trafficgen import ITrafficGenerator from tools.collectors.collector import ICollector +from tools.pkt_fwd.pkt_fwd import IPktFwd +from tools.pkt_gen.trafficgen import ITrafficGenerator from vswitches.vswitch import IVSwitch from vnfs.vnf.vnf import IVnf -from tools.pkt_fwd.pkt_fwd import IPktFwd class Loader(object): """Loader class - main object context holder. diff --git a/core/loader/loader_servant.py b/core/loader/loader_servant.py index 226b0931..8bad9ab9 100644 --- a/core/loader/loader_servant.py +++ b/core/loader/loader_servant.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -86,7 +86,8 @@ class LoaderServant(object): interface=self._interface) results = [] - for (name, mod) in list(out.items()): + # sort modules to produce the same output everytime + for (name, mod) in sorted(out.items()): desc = (mod.__doc__ or 'No description').strip().split('\n')[0] results.append((name, desc)) @@ -142,7 +143,7 @@ class LoaderServant(object): # find all classes derived from given interface, but suppress # interface itself and any abstract class starting with iface name gens = dict((k, v) for (k, v) in list(mod.__dict__.items()) - if type(v) == type and + if isinstance(v, type) and issubclass(v, interface) and not k.startswith(interface.__name__)) if gens: diff --git a/core/results/results_constants.py b/core/results/results_constants.py index 864712bc..2c733fe4 100644 --- a/core/results/results_constants.py +++ b/core/results/results_constants.py @@ -58,11 +58,11 @@ class ResultsConstants(object): SCAL_STREAM_COUNT = 'stream_count' SCAL_STREAM_TYPE = 'match_type' SCAL_PRE_INSTALLED_FLOWS = 'pre-installed_flows' - # RFC2889 Forwarding, Address-Caching and Congestion + # RFC2889 Forwarding, Address-Caching and Address-Learning FORWARDING_RATE_FPS = 'forwarding_rate_fps' - ADDRS_COUNT_FLOOD_COUNT_RATIO = 'addrs_count_flood_count_ratio' - CONGESTION_CONTROL_EXISTS = 'congestion_control_exists' - PORTS_MAP = 'ports_map' + CACHING_CAPACITY_ADDRS = 'caching_capacity_addrs' + ADDR_LEARNED_PERCENT = 'addr_learned_percent' + OPTIMAL_LEARNING_RATE_FPS = 'optimal_learning_rate_fps' TEST_RUN_TIME = "test_execution_time" diff --git a/core/traffic_controller_rfc2889.py b/core/traffic_controller_rfc2889.py index 210d5f5f..05955e65 100644 --- a/core/traffic_controller_rfc2889.py +++ b/core/traffic_controller_rfc2889.py @@ -50,13 +50,13 @@ class TrafficControllerRFC2889(TrafficController, IResults): else: traffic['l2'] = {'framesize': packet_size} - if traffic['traffic_type'] == 'caching': + if traffic['traffic_type'] == 'rfc2889_caching': result = self._traffic_gen_class.send_rfc2889_caching( - traffic, trials=self._trials, duration=self._duration) - elif traffic['traffic_type'] == 'congestion': - result = self._traffic_gen_class.send_rfc2889_congestion( - traffic, duration=self._duration) - else: + traffic, tests=self._trials, duration=self._duration) + elif traffic['traffic_type'] == 'rfc2889_learning': + result = self._traffic_gen_class.send_rfc2889_learning( + traffic, tests=self._trials, duration=self._duration) + elif traffic['traffic_type'] == 'rfc2889_forwarding': result = self._traffic_gen_class.send_rfc2889_forwarding( traffic, tests=self._trials, duration=self._duration) diff --git a/core/vnf_controller.py b/core/vnf_controller.py index 937cd5cc..78a29258 100644 --- a/core/vnf_controller.py +++ b/core/vnf_controller.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -67,10 +67,10 @@ class VnfController(object): # enforce that GUEST_NIC_NR is 1 or even number of NICs updated = False nics_nr = settings.getValue('GUEST_NICS_NR') - for index in range(len(nics_nr)): - if nics_nr[index] > 1 and nics_nr[index] % 2: + for index, value in enumerate(nics_nr): + if value > 1 and value % 2: updated = True - nics_nr[index] = int(nics_nr[index] / 2) * 2 + nics_nr[index] = int(value / 2) * 2 if updated: settings.setValue('GUEST_NICS_NR', nics_nr) self._logger.warning('Odd number of NICs was detected. Configuration ' diff --git a/docs/configguide/LICENSE b/docs/configguide/LICENSE new file mode 100644 index 00000000..7bc572ce --- /dev/null +++ b/docs/configguide/LICENSE @@ -0,0 +1,2 @@ +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 diff --git a/docs/configguide/index.rst b/docs/configguide/index.rst deleted file mode 100644 index b4c8575e..00000000 --- a/docs/configguide/index.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. This work is licensed under a Creative Commons Attribution 4.0 International License. -.. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, Intel Corporation, AT&T and others. - -****************************** -VSPERF Installation Guide -****************************** - -.. toctree:: - :numbered: - :maxdepth: 3 - - installation.rst - upgrade.rst - trafficgen.rst diff --git a/docs/configguide/installation.rst b/docs/configguide/installation.rst index b6b42bc2..1965a8f5 100644 --- a/docs/configguide/installation.rst +++ b/docs/configguide/installation.rst @@ -2,6 +2,8 @@ .. http://creativecommons.org/licenses/by/4.0 .. (c) OPNFV, Intel Corporation, AT&T and others. +.. _vsperf-installation: + ====================== Installing vswitchperf ====================== @@ -43,10 +45,9 @@ Supported Operating Systems --------------------------- * CentOS 7.3 -* Fedora 20 -* Fedora 21 -* Fedora 22 * Fedora 24 (kernel 4.8 requires DPDK 16.11 and newer) +* Fedora 25 (kernel 4.9 requires DPDK 16.11 and newer) +* openSUSE 42.2 * RedHat 7.2 Enterprise Linux * RedHat 7.3 Enterprise Linux * Ubuntu 14.04 @@ -122,6 +123,8 @@ Changelog of vloop-vnf: * version with development tools required for build of DPDK and l2fwd +.. _vsperf-installation-script: + Installation ------------ @@ -162,6 +165,22 @@ built from upstream source due to kernel incompatibilities. Please see the instructions in the vswitchperf_design document for details on configuring OVS Vanilla for binary package usage. +.. _vpp-installation: + +VPP installation +================ + +Currently vswitchperf installation scripts do not support automatic build +of VPP. In order to execute tests with VPP, it is required to install it +manually. Please refer to the official documentation of `fd.io`_ project to +install VPP from `packages`_ or from the `sources`_. + +See details about :ref:`vpp-test`. + +.. _fd.io: https://fd.io/ +.. _packages: https://wiki.fd.io/view/VPP/Installing_VPP_binaries_from_packages +.. _sources: https://wiki.fd.io/view/VPP/Build,_install,_and_test_images + Using vswitchperf ----------------- @@ -257,20 +276,10 @@ your configuration in the ``02_vswitch.conf`` file. .. 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`` is -used to configure vswitchd via ``ovs-vsctl`` calls. + DPDK_SOCKET_MEM = ['1024', '0'] -With the ``--socket-mem`` argument set to use 1 hugepage on the specified sockets as -seen above, the configuration will need 10 hugepages total to run all tests -within vsperf if the pagesize is set correctly to 1GB. +**NOTE:** Option ``DPDK_SOCKET_MEM`` is used by all vSwitches with DPDK support. +It means Open vSwitch, VPP and TestPMD. VSPerf will verify hugepage amounts are free before executing test environments. In case of hugepage amounts not being free, test initialization diff --git a/docs/configguide/trafficgen.rst b/docs/configguide/trafficgen.rst index b66a1787..4e42b2be 100644 --- a/docs/configguide/trafficgen.rst +++ b/docs/configguide/trafficgen.rst @@ -2,6 +2,8 @@ .. http://creativecommons.org/licenses/by/4.0 .. (c) OPNFV, Intel Corporation, AT&T and others. +.. _trafficgen-installation: + =========================== 'vsperf' Traffic Gen Guide =========================== @@ -87,6 +89,8 @@ commandline above to: $ ./vsperf --test-params "TRAFFICGEN_PKT_SIZES=(x,y);TRAFFICGEN_DURATION=10;" \ "TRAFFICGEN_RFC2544_TESTS=1" $TESTNAME +.. _trafficgen-dummy: + Dummy ----- @@ -410,22 +414,63 @@ RFC 2544 tests using the REST interface. Configuration: ~~~~~~~~~~~~~~ -The mandatory configurations are enlisted below. 1. The Labserver and license server addresses. These parameters applies to - all the tests and are mandatory. + all the tests, and are mandatory for all tests. .. code-block:: console TRAFFICGEN_STC_LAB_SERVER_ADDR = " " TRAFFICGEN_STC_LICENSE_SERVER_ADDR = " " + TRAFFICGEN_STC_PYTHON2_PATH = " " + TRAFFICGEN_STC_TESTCENTER_PATH = " " + TRAFFICGEN_STC_TEST_SESSION_NAME = " " + TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX = " " 2. For RFC2544 tests, the following parameters are mandatory +.. code-block:: console + + TRAFFICGEN_STC_EAST_CHASSIS_ADDR = " " + TRAFFICGEN_STC_EAST_SLOT_NUM = " " + TRAFFICGEN_STC_EAST_PORT_NUM = " " + TRAFFICGEN_STC_EAST_INTF_ADDR = " " + TRAFFICGEN_STC_EAST_INTF_GATEWAY_ADDR = " " + TRAFFICGEN_STC_WEST_CHASSIS_ADDR = "" + TRAFFICGEN_STC_WEST_SLOT_NUM = " " + TRAFFICGEN_STC_WEST_PORT_NUM = " " + TRAFFICGEN_STC_WEST_INTF_ADDR = " " + TRAFFICGEN_STC_WEST_INTF_GATEWAY_ADDR = " " + TRAFFICGEN_STC_RFC2544_TPUT_TEST_FILE_NAME + +3. RFC2889 tests: Currently, the forwarding, address-caching, and + address-learning-rate tests of RFC2889 are supported. + The testcenter-rfc2889-rest.py script implements the rfc2889 tests. + The configuration for RFC2889 involves test-case definition, and parameter + definition, as described below. New results-constants, as shown below, are + added to support these tests. + +Example of testcase definition for RFC2889 tests: + +.. code-block:: python + + { + "Name": "phy2phy_forwarding", + "Deployment": "p2p", + "Description": "LTD.Forwarding.RFC2889.MaxForwardingRate", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2889_forwarding", + }, + }, + } + +For RFC2889 tests, specifying the locations for the monitoring ports is mandatory. +Necessary parameters are: .. code-block:: console - TRAFFICGEN_STC_RFC2544_TPUT_TEST_FILE_NAME = " " + TRAFFICGEN_STC_RFC2889_TEST_FILE_NAME TRAFFICGEN_STC_EAST_CHASSIS_ADDR = " " TRAFFICGEN_STC_EAST_SLOT_NUM = " " TRAFFICGEN_STC_EAST_PORT_NUM = " " @@ -436,13 +481,52 @@ The mandatory configurations are enlisted below. TRAFFICGEN_STC_WEST_PORT_NUM = " " TRAFFICGEN_STC_WEST_INTF_ADDR = " " TRAFFICGEN_STC_WEST_INTF_GATEWAY_ADDR = " " + TRAFFICGEN_STC_VERBOSE = "True" + TRAFFICGEN_STC_RFC2889_LOCATIONS="//10.1.1.1/1/1,//10.1.1.1/2/2" + +Other Configurations are : + +.. code-block:: console + + TRAFFICGEN_STC_RFC2889_MIN_LR = 1488 + TRAFFICGEN_STC_RFC2889_MAX_LR = 14880 + TRAFFICGEN_STC_RFC2889_MIN_ADDRS = 1000 + TRAFFICGEN_STC_RFC2889_MAX_ADDRS = 65536 + TRAFFICGEN_STC_RFC2889_AC_LR = 1000 + +The first 2 values are for address-learning test where as other 3 values are +for the Address caching capacity test. LR: Learning Rate. AC: Address Caching. +Maximum value for address is 16777216. Whereas, maximum for LR is 4294967295. -3. For RFC2889 tests, specifying the locations of the ports is mandatory. +Results for RFC2889 Tests: Forwarding tests outputs following values: .. code-block:: console - TRAFFICGEN_STC_RFC2889_TEST_FILE_NAME = " " - TRAFFICGEN_STC_RFC2889_LOCATIONS= " " + TX_RATE_FPS : "Transmission Rate in Frames/sec" + THROUGHPUT_RX_FPS: "Received Throughput Frames/sec" + TX_RATE_MBPS : " Transmission rate in MBPS" + THROUGHPUT_RX_MBPS: "Received Throughput in MBPS" + TX_RATE_PERCENT: "Transmission Rate in Percentage" + FRAME_LOSS_PERCENT: "Frame loss in Percentage" + FORWARDING_RATE_FPS: " Maximum Forwarding Rate in FPS" + + +Whereas, the address caching test outputs following values, + +.. code-block:: console + + CACHING_CAPACITY_ADDRS = 'Number of address it can cache' + ADDR_LEARNED_PERCENT = 'Percentage of address successfully learned' + +and address learning test outputs just a single value: + +.. code-block:: console + + OPTIMAL_LEARNING_RATE_FPS = 'Optimal learning rate in fps' + +Note that 'FORWARDING_RATE_FPS', 'CACHING_CAPACITY_ADDRS', +'ADDR_LEARNED_PERCENT' and 'OPTIMAL_LEARNING_RATE_FPS' are the new +result-constants added to support RFC2889 tests. .. _`Xena Networks`: diff --git a/docs/configguide/upgrade.rst b/docs/configguide/upgrade.rst index 3a970c6a..cf92572c 100644 --- a/docs/configguide/upgrade.rst +++ b/docs/configguide/upgrade.rst @@ -120,9 +120,7 @@ options: In case that any of these options is defined, then configuration must be updated. All paths to the tools are now stored inside ``PATHS`` dictionary. Please -refer to the paths-documentation_ and update your configuration where necessary. - -.. _paths-documentation: http://artifacts.opnfv.org/vswitchperf/docs/index.html#configuration-of-paths-dictionary +refer to the :ref:`paths-documentation` and update your configuration where necessary. Configuration change via CLI ============================ @@ -134,7 +132,7 @@ possible to modify any configuration parameter via CLI or via **Parameters** section of the testcase definition. Old configuration options were obsoleted and it is required to specify configuration parameter name in the same form as it is defined inside configuration file, i.e. in uppercase. Please -refer to the overriding-parameters-documentation_ for additional details. +refer to the :ref:`overriding-parameters-documentation` for additional details. **NOTE:** In case that execution of VSPERF is automated by scripts (e.g. for CI purposes), then these scripts must be checked and updated too. It means, @@ -154,12 +152,9 @@ match to data types of original values from configuration files. In case that ``guest_nic1_name`` or ``guest_nic2_name`` is changed, then new dictionary ``GUEST_NICS`` must be modified accordingly. -Please see guest-configuration_ and ``conf/04_vnf.conf`` for additional +Please see :ref:`configuration-of-guest-options` and ``conf/04_vnf.conf`` for additional details. -.. _overriding-parameters-documentation: http://artifacts.opnfv.org/vswitchperf/docs/index.html#overriding-values-defined-in-configuration-files -.. _guest-configuration: http://artifacts.opnfv.org/vswitchperf/docs/index.html#configuration-of-guest-options - Traffic configuration via CLI ============================= @@ -167,7 +162,7 @@ In previous releases it was possible to modify selected attributes of generated traffic via command line interface. This concept has been enhanced in Danube release and it is now possible to modify all traffic specific options via CLI or by ``TRAFFIC`` dictionary in configuration file. Detailed description -is available at configuration-of-traffic-dictionary_ section of documentation. +is available at :ref:`configuration-of-traffic-dictionary` section of documentation. Please check your automated scripts for VSPERF execution for following CLI parameters and update them according to the documentation: @@ -186,4 +181,3 @@ parameters and update them according to the documentation: stream_type traffic_type -.. _configuration-of-traffic-dictionary: http://artifacts.opnfv.org/vswitchperf/docs/index.html#configuration-of-traffic-dictionary diff --git a/docs/design/LICENSE b/docs/design/LICENSE new file mode 100644 index 00000000..7bc572ce --- /dev/null +++ b/docs/design/LICENSE @@ -0,0 +1,2 @@ +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 diff --git a/docs/design/index.rst b/docs/design/index.rst deleted file mode 100644 index a8a076f4..00000000 --- a/docs/design/index.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. This work is licensed under a Creative Commons Attribution 4.0 International License. -.. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, Intel Corporation, AT&T and others. - -************** -VSPERF Design -************** - -.. toctree:: - :numbered: - :maxdepth: 3 - - vswitchperf_design.rst - - trafficgen_integration_guide.rst diff --git a/docs/design/trafficgen_integration_guide.rst b/docs/design/trafficgen_integration_guide.rst index 1457052b..382cedcb 100644 --- a/docs/design/trafficgen_integration_guide.rst +++ b/docs/design/trafficgen_integration_guide.rst @@ -11,8 +11,7 @@ Intended Audience This document is intended to aid those who want to integrate new traffic generator into the vsperf code. It is expected, that reader has already -read generic part of `VSPERF Design Document -<http://artifacts.opnfv.org/vswitchperf/docs/design/index.html>`__. +read generic part of :ref:`vsperf-design`. Let us create a sample traffic generator called **sample_tg**, step by step. @@ -132,6 +131,8 @@ Example in **tools/pkt_gen/sample_tg/sample_tg.py** module: def disconnect(self): pass +.. _step-5-supported-traffic-types: + Step 5 - supported traffic types ================================ @@ -192,7 +193,7 @@ functions: which are not listed below. Note: There are parameters specific to testing of tunnelling protocols, - which are discussed in detail at `integration tests userguide`_ + which are discussed in detail at :ref:`integration-tests` userguide. * param **traffic_type**: One of the supported traffic types, e.g. **rfc2544_throughput**, **rfc2544_continuous** @@ -235,5 +236,3 @@ are defined in **ResultsConstants** implemented in Throughput & Continuous and for Back2Back. The same key names should be used by all traffic generator implementations. -.. _integration tests userguide: http://artifacts.opnfv.org/vswitchperf/docs/userguide/integration.html - diff --git a/docs/design/vswitchperf_design.rst b/docs/design/vswitchperf_design.rst index bf82f9b8..da7ec6fd 100644 --- a/docs/design/vswitchperf_design.rst +++ b/docs/design/vswitchperf_design.rst @@ -2,6 +2,8 @@ .. http://creativecommons.org/licenses/by/4.0 .. (c) OPNFV, Intel Corporation, AT&T and others. +.. _vsperf-design: + ====================== VSPERF Design Document ====================== @@ -63,6 +65,7 @@ This is a typical flow of control for a test. .. image:: vsperf.png +.. _design-configuration: Configuration ============= @@ -101,11 +104,13 @@ The values in the file specified by ``--conf-file`` takes precedence over all the other configuration files and does not have to follow the naming convention. +.. _paths-documentation: + Configuration of PATHS dictionary --------------------------------- VSPERF uses external tools like Open vSwitch and Qemu for execution of testcases. These -tools may be downloaded and built automatically by `VSPERF installation scripts`_ +tools may be downloaded and built automatically (see :ref:`vsperf-installation-script`) or installed manually by user from binary packages. It is also possible to use a combination of both approaches, but it is essential to correctly set paths to all required tools. These paths are stored within a PATHS dictionary, which is evaluated before execution @@ -261,7 +266,7 @@ Note: In case of RHEL 7.3 OS usage, binary package configuration is required for Vanilla OVS tests. With the installation of a supported rpm for OVS there is a section in the ``conf\10_custom.conf`` file that can be used. -.. _VSPERF installation scripts: http://artifacts.opnfv.org/vswitchperf/docs/configguide/installation.html#other-requirements +.. _configuration-of-traffic-dictionary: Configuration of TRAFFIC dictionary ----------------------------------- @@ -388,6 +393,8 @@ Detailed description of ``TRAFFIC`` dictionary items follows: Data type: int (NOTE: must fit to 1 bit) Default value: 0 +.. _configuration-of-guest-options: + Configuration of GUEST options ------------------------------ @@ -491,6 +498,8 @@ Other Configuration ``conf.settings`` also loads configuration from the command line and from the environment. +.. _pxp-deployment: + PXP Deployment ============== diff --git a/docs/index.rst b/docs/index.rst index bce2aa61..889d4ab6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,6 +1,6 @@ .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, Intel Corporation, AT&T and others. +.. (c) OPNFV, Intel Corporation, AT&T, Red Hat, Spirent, Ixia and others. .. OPNFV VSPERF Documentation master file. @@ -9,28 +9,84 @@ VSPERF ====== VSPERF is an OPNFV testing project. -VSPERF will develop a generic and architecture agnostic vSwitch testing -framework and associated tests, that will serve as a basis for validating the -suitability of different vSwitch implementations in a Telco NFV deployment -environment. The output of this project will be utilized by the OPNFV -Performance and Test group and its associated projects, as part of OPNFV -Platform and VNF level testing and validation. +VSPERF provides an automated test-framework and comprehensive test suite based on +industry standards for measuring data-plane performance of Telco NFV switching +technologies as well as physical and virtual network interfaces (NFVI). The VSPERF +architecture is switch and traffic generator agnostic and provides full control of +software component versions and configurations as well as test-case customization. -* Project Wiki: https://wiki.opnfv.org/characterize_vswitch_performance_for_telco_nfv_use_cases -* Project Repository: https://git.opnfv.org/vswitchperf -* Project Artifacts: https://artifacts.opnfv.org/vswitchperf.html -* Continuous Integration https://build.opnfv.org/ci/view/vswitchperf/ +The Danube release of VSPERF includes improvements in documentation and capabilities. +This includes additional test-cases such as RFC 5481 Latency test and RFC-2889 +address-learning-rate test. Hardware traffic generator support is now provided for +Spirent and Xena in addition to Ixia. The Moongen software traffic generator is also +now fully supported. VSPERF can be used in a variety of modes for configuration and +setup of the network and/or for control of the test-generator and test execution. + +* Wiki: https://wiki.opnfv.org/characterize_vswitch_performance_for_telco_nfv_use_cases +* Repository: https://git.opnfv.org/vswitchperf +* Artifacts: https://artifacts.opnfv.org/vswitchperf.html +* Continuous Integration status: https://build.opnfv.org/ci/view/vswitchperf/ + +****************************** +VSPERF Installation Guide +****************************** .. toctree:: - :maxdepth: 3 + :caption: VSPERF Installation Guide + :maxdepth: 5 + :numbered: 5 + + ./configguide/installation.rst + ./configguide/upgrade.rst + ./configguide/trafficgen.rst + +****************************** +VSPERF User Guide +****************************** + +.. toctree:: + :caption: VSPERF User Guide + :maxdepth: 5 :numbered: 5 - ./configguide/index.rst - ./userguide/index.rst - ./design/index.rst - ./requirements/index.rst - ./release/index.rst - ./results/index.rst + ./userguide/testusage.rst + ./userguide/teststeps.rst + ./userguide/integration.rst + Yardstick integration <./userguide/yardstick.rst> + +************** +VSPERF Design +************** + +.. toctree:: + :caption: VSPERF Design + :maxdepth: 5 + :numbered: 5 + + ./design/vswitchperf_design.rst + ./design/trafficgen_integration_guide.rst + +******************* +VSPERF Requirements +******************* + +.. toctree:: + :caption: VSPERF Requirements + :maxdepth: 5 + :numbered: 5 + + ./requirements/vswitchperf_ltp.rst + ./requirements/vswitchperf_ltd.rst + +************** +VSPERF Results +************** + +.. toctree:: + :maxdepth: 3 + + ./results/scenario.rst + ./results/results.rst Indices ======= diff --git a/docs/release/index.rst b/docs/release/index.rst deleted file mode 100644 index bf0b9d18..00000000 --- a/docs/release/index.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. This work is licensed under a Creative Commons Attribution 4.0 International License. -.. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, Intel Corporation, AT&T and others. - -*********** -VSPERF News -*********** - -.. toctree:: - :numbered: - :maxdepth: 3 - - NEWS.rst diff --git a/docs/release/NEWS.rst b/docs/release/release-notes/vsperf-release.rst index a31e2738..52a01abc 100644 --- a/docs/release/NEWS.rst +++ b/docs/release/release-notes/vsperf-release.rst @@ -2,6 +2,10 @@ .. http://creativecommons.org/licenses/by/4.0 .. (c) OPNFV, Intel Corporation, AT&T and others. +******************** +VSPERF Release Notes +******************** + OPNFV Danube Release ==================== @@ -16,6 +20,7 @@ OPNFV Danube Release * Support for Ubuntu 16.04 LTS and 16.10 * Support for RHEL7.3 * Support for CentOS7.3 + * Support for openSUSE Leap 42.2 * Traffic Generators: diff --git a/docs/requirements/LICENSE b/docs/requirements/LICENSE new file mode 100644 index 00000000..7bc572ce --- /dev/null +++ b/docs/requirements/LICENSE @@ -0,0 +1,2 @@ +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 diff --git a/docs/requirements/ietf_draft/LICENSE b/docs/requirements/ietf_draft/LICENSE new file mode 100644 index 00000000..7fc9ae14 --- /dev/null +++ b/docs/requirements/ietf_draft/LICENSE @@ -0,0 +1,12 @@ +Copyright (c) 2016 IETF Trust and the persons identified as the +document authors. All rights reserved. + +This document is subject to BCP 78 and the IETF Trust's Legal +Provisions Relating to IETF Documents +(http://trustee.ietf.org/license-info) in effect on the date of +publication of this document. Please review these documents +carefully, as they describe your rights and restrictions with respect +to this document. Code Components extracted from this document must +include Simplified BSD License text as described in Section 4.e of +the Trust Legal Provisions and are provided without warranty as +described in the Simplified BSD License. diff --git a/docs/requirements/index.rst b/docs/requirements/index.rst deleted file mode 100644 index 311ddb07..00000000 --- a/docs/requirements/index.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. This work is licensed under a Creative Commons Attribution 4.0 International License. -.. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, Intel Corporation, AT&T and others. - -.. toctree:: - :maxdepth: 3 - :numbered: 5 - - vswitchperf_ltp.rst - vswitchperf_ltd.rst - diff --git a/docs/requirements/vswitchperf_ltd.rst b/docs/requirements/vswitchperf_ltd.rst index 69497c5c..e1372520 100644 --- a/docs/requirements/vswitchperf_ltd.rst +++ b/docs/requirements/vswitchperf_ltd.rst @@ -127,6 +127,8 @@ expected that more will be added. .. 3.2.2.1.1 +.. _PacketLossRatio: + Test ID: LTD.Throughput.RFC2544.PacketLossRatio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -144,8 +146,8 @@ Test ID: LTD.Throughput.RFC2544.PacketLossRatio Note: Other values can be tested if required by the user. - The selected frame sizes are those previously defined under `Default - Test Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__. + The selected frame sizes are those previously defined under + :ref:`default-test-parameters`. The test can also be used to determine the average latency of the traffic. Under the `RFC2544 <https://www.rfc-editor.org/rfc/rfc2544.txt>`__ @@ -178,6 +180,8 @@ Test ID: LTD.Throughput.RFC2544.PacketLossRatio .. 3.2.2.1.2 +.. _PacketLossRatioFrameModification: + Test ID: LTD.Throughput.RFC2544.PacketLossRatioFrameModification ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -196,8 +200,8 @@ Test ID: LTD.Throughput.RFC2544.PacketLossRatioFrameModification Note: Other values can be tested if required by the user. - The selected frame sizes are those previously defined under `Default - Test Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__. + The selected frame sizes are those previously defined under + :ref:`default-test-parameters`. The test can also be used to determine the average latency of the traffic. Under the `RFC2544 <https://www.rfc-editor.org/rfc/rfc2544.txt>`__ @@ -267,8 +271,8 @@ Test ID: LTD.Throughput.RFC2544.Profile and latency as the offered rate increases is slow and graceful or sudden and severe. - The selected frame sizes are those previously defined under `Default - Test Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__. + The selected frame sizes are those previously defined under + :ref:`default-test-parameters`. The offered traffic rate is described as a percentage delta with respect to the DUT's RFC 2544 Throughput as determined by @@ -319,8 +323,7 @@ Test ID: LTD.Throughput.RFC2544.SystemRecoveryTime The aim of this test is to determine the length of time it takes the DUT to recover from an overload condition for a constant load (fixed length frames at a fixed interval time). The selected frame sizes are those - previously defined under `Default Test Parameters - <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__, + previously defined under :ref:`default-test-parameters`, traffic should be sent to the DUT under normal conditions. During the duration of the test and while the traffic flows are passing though the DUT, at least one situation leading to an overload condition for the DUT @@ -359,6 +362,8 @@ Test ID: LTD.Throughput.RFC2544.SystemRecoveryTime .. 3.2.2.1.5 +.. _BackToBackFrames: + Test ID: LTD.Throughput.RFC2544.BackToBackFrames ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -372,9 +377,7 @@ Test ID: LTD.Throughput.RFC2544.BackToBackFrames The aim of this test is to characterize the ability of the DUT to process back-to-back frames. For each frame size previously defined - under `Default Test Parameters - <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__, - a burst of traffic + under :ref:`default-test-parameters`, a burst of traffic is sent to the DUT with the minimum inter-frame gap between each frame. If the number of received frames equals the number of frames that were transmitted, the burst size should be increased and traffic is sent to @@ -527,8 +530,7 @@ Test ID: LTD.Throughput.RFC6201.ResetTime Both reset methods SHOULD be exercised. - For each frame size previously defined under `Default Test - Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__, + For each frame size previously defined under :ref:`default-test-parameters`, traffic should be sent to the DUT under normal conditions. During the duration of the test and while the traffic flows are passing through the DUT, the DUT should be reset and the Reset @@ -613,8 +615,7 @@ Test ID: LTD.Throughput.RFC2889.MaxForwardingRate This test measures the DUT's Max Forwarding Rate when the Offered Load is varied between the throughput and the Maximum Offered Load for fixed length frames at a fixed time interval. The selected frame sizes are - those previously defined under `Default Test - Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__. + those previously defined under :ref:`default-test-parameters`. The throughput is the maximum offered load with 0% frame loss (measured by the prerequisite test), and the Maximum Offered Load (as defined by @@ -749,8 +750,7 @@ Test ID: LTD.Throughput.RFC2889.BroadcastFrameForwarding The aim of this test is to determine the maximum forwarding rate of the DUT when forwarding broadcast traffic. For each frame previously defined - under `Default Test Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__, - the traffic should + under :ref:`default-test-parameters`, the traffic should be set up as broadcast traffic. The traffic throughput of the DUT should be measured. @@ -917,8 +917,8 @@ Test ID: LTD.Throughput.Overlay.Network.<tech>.RFC2544.PacketLossRatio - De-encapsulate the packet, if required - Switch the packet to the correct port - The selected frame sizes are those previously defined under `Default - Test Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__. + The selected frame sizes are those previously defined under + :ref:`default-test-parameters`. Thus, each test comprises an overlay technology, a network function, and a packet size *with* overlay network overhead included @@ -1041,8 +1041,8 @@ Test ID: LTD.Throughput.RFC2544.MatchAction.PacketLossRatio The default loss percentages to be tested are: - X = 0% - X = 10^-7% Other values can be tested if required by the user. The selected - frame sizes are those previously defined under `Default Test Parameters - <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__. + frame sizes are those previously defined under + :ref:`default-test-parameters`. The test can also be used to determine the average latency of the traffic when a match action is applied to packets in a flow. Under @@ -1189,6 +1189,8 @@ It is expected that more will be added. .. 3.2.2.3.1 +.. _Scalability0PacketLoss: + Test ID: LTD.Scalability.Flows.RFC2544.0PacketLoss ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1207,8 +1209,7 @@ Test ID: LTD.Scalability.Flows.RFC2544.0PacketLoss through the fastpath, as such the flows need to be installed on the DUT before passing traffic. - For each frame size previously defined under `Default Test - Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__ + For each frame size previously defined under :ref:`default-test-parameters` and for each of the following number of flows: - 1,000 @@ -1336,8 +1337,8 @@ Test ID: LTD.Scalability.VNF.RFC2544.PacketLossRatio would be to continue to add VNFs without bringing down the DUT. The approach used needs to be documented as part of the test report. - The selected frame sizes are those previously defined under `Default - Test Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__. + The selected frame sizes are those previously defined under + :ref:`default-test-parameters`. The test can also be used to determine the average latency of the traffic. Under the `RFC2544 <https://www.rfc-editor.org/rfc/rfc2544.txt>`__ @@ -1397,8 +1398,8 @@ Test ID: LTD.Scalability.VNF.RFC2544.PacketLossProfile and graceful, or sudden and severe. The minimum number of VNFs to be tested is 3. - The selected frame sizes are those previously defined under `Default - Test Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__. + The selected frame sizes are those previously defined under + :ref:`default-test-parameters`. The offered traffic rate is described as a percentage delta with respect to the DUT's RFC 2544 Throughput as determined by @@ -1479,8 +1480,7 @@ Test ID: LTD.Activation.RFC2889.AddressCachingCapacity MAC learning. The aim of this test is to determine the address caching capacity of the DUT for a constant load (fixed length frames at a fixed interval time). The selected frame sizes are those previously defined - under `Default Test Parameters - <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__. + under :ref:`default-test-parameters`. In order to run this test the aging time, that is the maximum time the DUT will keep a learned address in its flow table, and a set of initial @@ -1533,8 +1533,7 @@ Test ID: LTD.Activation.RFC2889.AddressLearningRate MAC learning. The aim of this test is to determine the rate of address learning of the DUT for a constant load (fixed length frames at a fixed interval time). The selected frame sizes are those previously defined - under `Default Test Parameters <http://artifacts.opnfv.org/vswitchperf/docs/index.html#default-test-parameters>`__, - traffic should be + under :ref:`default-test-parameters`, traffic should be sent with each IPv4/IPv6 address incremented by one. The rate at which the DUT learns a new address should be measured. The maximum caching capacity from LTD.Memory.RFC2889.AddressCachingCapacity should be taken @@ -1626,6 +1625,8 @@ should be required. It is expected that more will be added. .. 3.2.2.6.1 +.. _CPU0PacketLoss: + Test ID: LTD.Stress.RFC2544.0PacketLoss ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/requirements/vswitchperf_ltp.rst b/docs/requirements/vswitchperf_ltp.rst index 14303de5..2b74d676 100644 --- a/docs/requirements/vswitchperf_ltp.rst +++ b/docs/requirements/vswitchperf_ltp.rst @@ -303,6 +303,8 @@ datapaths to physical ports (to NICs) and to logical ports (to VNFs): .. 3.2.5.1.1 +.. _Phy2Phy: + Physical port → vSwitch → physical port ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: console @@ -326,6 +328,8 @@ Physical port → vSwitch → physical port .. 3.2.5.1.2 +.. _PVP: + Physical port → vSwitch → VNF → vSwitch → physical port ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: console @@ -365,6 +369,8 @@ Physical port → vSwitch → VNF → vSwitch → physical port .. 3.2.5.1.3 +.. _PVVP: + Physical port → vSwitch → VNF → vSwitch → VNF → vSwitch → physical port ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -639,6 +645,8 @@ Suitable real Telco workload VNFs are yet to be identified. .. 3.2.5.2.1 +.. _default-test-parameters: + Default Test Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/results/index.rst b/docs/results/index.rst deleted file mode 100644 index 04899b5a..00000000 --- a/docs/results/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. This work is licensed under a Creative Commons Attribution 4.0 International License. -.. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, Intel Corporation, AT&T and others. - -************** -VSPERF Results -************** - -.. toctree:: - :numbered: - :maxdepth: 3 - - scenario.rst - results.rst diff --git a/docs/results/scenario.rst b/docs/results/scenario.rst index cb42c8dc..49ff626a 100644 --- a/docs/results/scenario.rst +++ b/docs/results/scenario.rst @@ -9,34 +9,33 @@ Available Tests and aspects of scenarios: ===================== =========================================================== Framework Test Definition ===================== =========================================================== -phy2phy_tput PacketLossRatio_ for Phy2Phy_ -back2back BackToBackFrames_ for Phy2Phy_ -phy2phy_tput_mod_vlan PacketLossRatioFrameModification_ for Phy2Phy_ -phy2phy_cont Phy2Phy_ blast vswitch at x% TX rate and measure throughput -pvp_cont PVP_ blast vswitch at x% TX rate and measure throughput -pvvp_cont PVVP_ blast vswitch at x% TX rate and measure throughput -phy2phy_scalability Scalability0PacketLoss_ for Phy2Phy_ -pvp_tput PacketLossRatio_ for PVP_ -pvp_back2back BackToBackFrames_ for PVP_ -pvvp_tput PacketLossRatio_ for PVVP_ -pvvp_back2back BackToBackFrames_ for PVVP_ -phy2phy_cpu_load CPU0PacketLoss_ for Phy2Phy_ -phy2phy_mem_load Same as CPU0PacketLoss_ but using a memory intensive app +phy2phy_tput :ref:`PacketLossRatio <PacketLossRatio>` for :ref:`Phy2Phy <Phy2Phy>` +back2back :ref:`BackToBackFrames <BackToBackFrames>` for :ref:`Phy2Phy <Phy2Phy>` +phy2phy_tput_mod_vlan :ref:`PacketLossRatioFrameModification <PacketLossRatioFrameModification>` for :ref:`Phy2Phy <Phy2Phy>` +phy2phy_cont :ref:`Phy2Phy <Phy2Phy>` blast vswitch at x% TX rate and measure throughput +pvp_cont :ref:`PVP <PVP>` blast vswitch at x% TX rate and measure throughput +pvvp_cont :ref:`PVVP <PVVP>` blast vswitch at x% TX rate and measure throughput +phy2phy_scalability :ref:`Scalability0PacketLoss <Scalability0PacketLoss>` for :ref:`Phy2Phy <Phy2Phy>` +pvp_tput :ref:`PacketLossRatio <PacketLossRatio>` for :ref:`PVP <PVP>` +pvp_back2back :ref:`BackToBackFrames <BackToBackFrames>` for :ref:`PVP <PVP>` +pvvp_tput :ref:`PacketLossRatio <PacketLossRatio>` for :ref:`PVVP <PVVP>` +pvvp_back2back :ref:`BackToBackFrames <BackToBackFrames>` for :ref:`PVVP <PVVP>` +phy2phy_cpu_load :ref:`CPU0PacketLoss <CPU0PacketLoss>` for :ref:`Phy2Phy <Phy2Phy>` +phy2phy_mem_load Same as :ref:`CPU0PacketLoss <CPU0PacketLoss>` but using a memory intensive app ===================== =========================================================== Supported deployment scenarios: -* Phy2Phy_: Physical port -> vSwitch -> Physical port. -* PVP_: Physical port -> vSwitch -> VNF -> vSwitch -> Physical port. -* PVVP_: Physical port -> vSwitch -> VNF -> vSwitch -> VNF -> vSwitch -> +* :ref:`Phy2Phy <Phy2Phy>`: Physical port -> vSwitch -> Physical port. +* :ref:`PVP <PVP>`: Physical port -> vSwitch -> VNF -> vSwitch -> Physical port. +* :ref:`PVVP <PVVP>`: Physical port -> vSwitch -> VNF -> vSwitch -> VNF -> vSwitch -> Physical port. Loopback applications in the Guest can be: * `DPDK testpmd <http://dpdk.org/doc/guides/testpmd_app_ug/index.html>`_. * Linux Bridge. -* `l2fwd - <http://artifacts.opnfv.org/vswitchperf/docs/userguide/testusage.html#l2fwd-kernel-module>`_. +* :ref:`l2fwd-module` Supported traffic generators: @@ -44,19 +43,3 @@ Supported traffic generators: * Spirent. * Dummy. -.. _PacketLossRatio: http://artifacts.opnfv.org/vswitchperf/docs/requirements/vswitchperf_ltd.html#test-id-ltd-throughput-rfc2544-packetlossratio - -.. _BackToBackFrames: http://artifacts.opnfv.org/vswitchperf/docs/requirements/vswitchperf_ltd.html#test-id-ltd-throughput-rfc2544-backtobackframes - -.. _PacketLossRatioFrameModification: http://artifacts.opnfv.org/vswitchperf/docs/requirements/vswitchperf_ltd.html#test-id-ltd-throughput-rfc2544-packetlossratioframemodification - -.. _Scalability0PacketLoss: http://artifacts.opnfv.org/vswitchperf/docs/requirements/vswitchperf_ltd.html#test-id-ltd-scalability-flows-rfc2544-0packetloss - -.. _CPU0PacketLoss: http://artifacts.opnfv.org/vswitchperf/docs/requirements/vswitchperf_ltd.html#test-id-ltd-stress-rfc2544-0packetloss - -.. _Phy2Phy : http://artifacts.opnfv.org/vswitchperf/docs/requirements/vswitchperf_ltp.html#physical-port-vswitch-physical-port - -.. _PVP: http://artifacts.opnfv.org/vswitchperf/docs/requirements/vswitchperf_ltp.html#physical-port-vswitch-vnf-vswitch-physical-port - -.. _PVVP: http://artifacts.opnfv.org/vswitchperf/docs/requirements/vswitchperf_ltp.html#physical-port-vswitch-vnf-vswitch-vnf-vswitch-physical-port - diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst deleted file mode 100644 index a1cce262..00000000 --- a/docs/userguide/index.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. This work is licensed under a Creative Commons Attribution 4.0 International License. -.. http://creativecommons.org/licenses/by/4.0 -.. (c) OPNFV, Intel Corporation, AT&T and others. - -****************************** -VSPERF User Guide -****************************** - -.. toctree:: - :numbered: - :maxdepth: 3 - - testusage.rst - teststeps.rst - integration.rst - yardstick.rst diff --git a/docs/userguide/integration.rst b/docs/userguide/integration.rst index 60ed9245..83b29da6 100644 --- a/docs/userguide/integration.rst +++ b/docs/userguide/integration.rst @@ -2,6 +2,8 @@ .. http://creativecommons.org/licenses/by/4.0 .. (c) OPNFV, Intel Corporation, AT&T and others. +.. _integration-tests: + Integration tests ================= diff --git a/docs/userguide/teststeps.rst b/docs/userguide/teststeps.rst index 5029f538..870c3d80 100644 --- a/docs/userguide/teststeps.rst +++ b/docs/userguide/teststeps.rst @@ -2,6 +2,8 @@ .. http://creativecommons.org/licenses/by/4.0 .. (c) OPNFV, Intel Corporation, AT&T and others. +.. _step-driven-tests: + Step driven tests ================= @@ -115,8 +117,8 @@ of supported objects and their most common functions follows: * ``send_traffic traffic`` - starts a traffic based on the vsperf configuration and given ``traffic`` dictionary. More details about ``traffic`` dictionary - and its possible values are available at `Traffic Generator Integration Guide - <http://artifacts.opnfv.org/vswitchperf/docs/design/trafficgen_integration_guide.html#step-5-supported-traffic-types>`__ + and its possible values are available at :ref:`Traffic Generator Integration Guide + <step-5-supported-traffic-types>` Examples: diff --git a/docs/userguide/testusage.rst b/docs/userguide/testusage.rst index 721fd635..c6037aaf 100644 --- a/docs/userguide/testusage.rst +++ b/docs/userguide/testusage.rst @@ -21,23 +21,19 @@ support in VSPERF includes: - Moongen software traffic generator. Requires a separate machine running moongen to execute packet generation. -If you want to use another traffic generator, please select the Dummy generator -option as shown in `Traffic generator instructions -<http://artifacts.opnfv.org/vswitchperf/docs/configguide/trafficgen.html>`__ +If you want to use another traffic generator, please select the :ref:`trafficgen-dummy` +generator. VSPERF Installation ^^^^^^^^^^^^^^^^^^^ To see the supported Operating Systems, vSwitches and system requirements, -please follow the `installation instructions -<http://artifacts.opnfv.org/vswitchperf/docs/configguide/installation.html>`__ to -install. +please follow the `installation instructions <vsperf-installation>`. Traffic Generator Setup ^^^^^^^^^^^^^^^^^^^^^^^ -Follow the `Traffic generator instructions -<http://artifacts.opnfv.org/vswitchperf/docs/configguide/trafficgen.html>`__ to +Follow the `Traffic generator instructions <trafficgen-installation>` to install and configure a suitable traffic generator. Cloning and building src dependencies @@ -86,8 +82,8 @@ contents. Any configuration item mentioned in any .conf file in the custom configuration value. Further details about configuration files evaluation and special behaviour -of options with ``GUEST_`` prefix could be found at `design document -<http://artifacts.opnfv.org/vswitchperf/docs/design/vswitchperf_design.html#configuration>`__. +of options with ``GUEST_`` prefix could be found at :ref:`design document +<design-configuration>`. Using a custom settings file ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,8 +107,10 @@ described like so (1 = max priority): 4. Configuration file(s) Further details about configuration files evaluation and special behaviour -of options with ``GUEST_`` prefix could be found at `design document -<http://artifacts.opnfv.org/vswitchperf/docs/design/vswitchperf_design.html#configuration>`__. +of options with ``GUEST_`` prefix could be found at :ref:`design document +<design-configuration>`. + +.. _overriding-parameters-documentation: Overriding values defined in configuration files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -163,27 +161,14 @@ section of test case definition. It is also forbidden to redefine a value of vloop_vnf ^^^^^^^^^ -vsperf uses a VM image called vloop_vnf for looping traffic in the deployment +VSPERF uses a VM image called vloop_vnf for looping traffic in the deployment scenarios involving VMs. The image can be downloaded from `<http://artifacts.opnfv.org/>`__. -.. code-block:: console - - $ wget http://artifacts.opnfv.org/vswitchperf/vloop-vnf-ubuntu-14.04_20151216.qcow2 - -Newer vloop_vnf images are available. Please reference the -installation instructions for information on these images -`installation instructions -<http://artifacts.opnfv.org/vswitchperf/docs/configguide/installation.html>`__ - - -vloop_vnf forwards traffic through a VM using one of: +Please see the installation instructions for information on :ref:`vloop-vnf` +images. -* DPDK testpmd -* Linux Bridge -* l2fwd kernel Module. - -Alternatively you can use your own QEMU image. +.. _l2fwd-module: l2fwd Kernel Module ^^^^^^^^^^^^^^^^^^^ @@ -350,6 +335,43 @@ To run tests using Vanilla OVS: $ ./vsperf --conf-file<path_to_custom_conf>/10_custom.conf +.. _vpp-test: + +Executing VPP tests +^^^^^^^^^^^^^^^^^^^ + +Currently it is not possible to use standard scenario deployments for execution of +tests with VPP. It means, that deployments ``p2p``, ``pvp``, ``pvvp`` and in general any +:ref:`pxp-deployment` won't work with VPP. However it is possible to use VPP in +:ref:`step-driven-tests`. A basic set of VPP testcases covering ``phy2phy``, ``pvp`` +and ``pvvp`` tests are already prepared. + +List of performance tests with VPP support follows: + +* phy2phy_tput_vpp: VPP: LTD.Throughput.RFC2544.PacketLossRatio +* phy2phy_cont_vpp: VPP: Phy2Phy Continuous Stream +* phy2phy_back2back_vpp: VPP: LTD.Throughput.RFC2544.BackToBackFrames +* pvp_tput_vpp: VPP: LTD.Throughput.RFC2544.PacketLossRatio +* pvp_cont_vpp: VPP: PVP Continuous Stream +* pvp_back2back_vpp: VPP: LTD.Throughput.RFC2544.BackToBackFrames +* pvvp_tput_vpp: VPP: LTD.Throughput.RFC2544.PacketLossRatio +* pvvp_cont_vpp: VPP: PVP Continuous Stream +* pvvp_back2back_vpp: VPP: LTD.Throughput.RFC2544.BackToBackFrames + +In order to execute testcases with VPP it is required to: + +* install VPP manually, see :ref:`vpp-installation` +* configure ``WHITELIST_NICS``, with two physical NICs connected to the traffic generator +* configure traffic generator, see :ref:`trafficgen-installation` + +After that it is possible to execute VPP testcases listed above. + +For example: + +.. code-block:: console + + $ ./vsperf --conf-file=<path_to_custom_conf> phy2phy_tput_vpp + .. _vfio-pci: Using vfio_pci with DPDK @@ -704,7 +726,8 @@ application to use the correct number of nb-cores. .. code-block:: python - VSWITCHD_DPDK_ARGS = ['-l', '46,44,42,40,38', '-n', '4', '--socket-mem 1024,0'] + DPDK_SOCKET_MEM = ['1024', '0'] + VSWITCHD_DPDK_ARGS = ['-l', '46,44,42,40,38', '-n', '4'] TESTPMD_ARGS = ['--nb-cores=4', '--txq=1', '--rxq=1'] For guest TestPMD 3 VCpus should be assigned with the following TestPMD params. @@ -748,8 +771,7 @@ of traffic generator can be modified through ``TRAFFIC`` dictionary passed to th ``--test-params`` option. It is not needed to specify all values of ``TRAFFIC`` dictionary. It is sufficient to specify only values, which should be changed. Detailed description of ``TRAFFIC`` dictionary can be found at -`Configuration of TRAFFIC dictionary -<http://artifacts.opnfv.org/vswitchperf/docs/index.html#configuration-of-traffic-dictionary>`__ +:ref:`configuration-of-traffic-dictionary`. Example of execution of VSPERF in "trafficgen" mode: @@ -806,21 +828,21 @@ an appropriate amount of memory: .. code-block:: python - VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4', '--socket-mem 1024,0'] + DPDK_SOCKET_MEM = ['1024', '0'] + VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4'] 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. +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 ^^^^^^^^^^^^^^^^ -For more information and details refer to the vSwitchPerf user guide at: -http://artifacts.opnfv.org/vswitchperf/docs/userguide/index.html +For more information and details refer to the rest of vSwitchPerfuser documentation. diff --git a/docs/userguide/yardstick.rst b/docs/userguide/yardstick.rst index c906df8e..b5e5c72d 100644 --- a/docs/userguide/yardstick.rst +++ b/docs/userguide/yardstick.rst @@ -65,14 +65,10 @@ Preparation of custom VM image In general, any Linux distribution supported by vswitchperf can be used as a base image for vswitchperf. One of the possibilities is to modify vloop-vnf -image, which can be downloaded from `<http://artifacts.opnfv.org/vswitchperf.html/>`__. +image, which can be downloaded from `<http://artifacts.opnfv.org/vswitchperf.html/>`__ +(see :ref:`vloop-vnf`). -.. code-block:: console - - $ wget http://artifacts.opnfv.org/vswitchperf/vnf/vloop-vnf-ubuntu-14.04_20160823.qcow2 - -Please follow the `installation instructions -<http://artifacts.opnfv.org/vswitchperf/docs/configguide/installation.html>`__ to +Please follow the :ref:`vsperf-installation` to install vswitchperf inside vloop-vnf image. As vswitchperf will be run in trafficgen mode, it is possible to skip installation and compilation of OVS, QEMU and DPDK to keep image size smaller. diff --git a/fuel-plugin-vsperf/README.md b/fuel-plugin-vsperf/README.md index a7dca2c1..5e7e9346 100644 --- a/fuel-plugin-vsperf/README.md +++ b/fuel-plugin-vsperf/README.md @@ -1,3 +1,8 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + fuel-plugin-vsperf ================== diff --git a/fuel-plugin-vsperf/deployment_scripts/deploy.sh b/fuel-plugin-vsperf/deployment_scripts/deploy.sh index 6c82e46d..084d1e3e 100755 --- a/fuel-plugin-vsperf/deployment_scripts/deploy.sh +++ b/fuel-plugin-vsperf/deployment_scripts/deploy.sh @@ -1,4 +1,11 @@ #!/bin/bash +# Copyright (c) 2016-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + # It's a script which deploys your plugin diff --git a/fuel-plugin-vsperf/deployment_scripts/puppet/manifests/vsperf-install.pp b/fuel-plugin-vsperf/deployment_scripts/puppet/manifests/vsperf-install.pp index 7d075add..43787c7b 100644 --- a/fuel-plugin-vsperf/deployment_scripts/puppet/manifests/vsperf-install.pp +++ b/fuel-plugin-vsperf/deployment_scripts/puppet/manifests/vsperf-install.pp @@ -1,5 +1,11 @@ -$fuel_settings = parseyaml(file('/etc/astute.yaml')) -$master_ip = $::fuel_settings['master_ip'] +# Copyright (c) 2016-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +$master_ip = hiera('master_ip') exec { "install vsperf": command => "mkdir -p /opt/vswitchperf; curl http://$master_ip:8080/plugins/fuel-plugin-vsperf-1.0/repositories/ubuntu/vswitchperf.tgz | tar xzv -C /opt/vswitchperf", diff --git a/fuel-plugin-vsperf/deployment_tasks.yaml b/fuel-plugin-vsperf/deployment_tasks.yaml index 02a7c56b..d37f1545 100644 --- a/fuel-plugin-vsperf/deployment_tasks.yaml +++ b/fuel-plugin-vsperf/deployment_tasks.yaml @@ -1,3 +1,10 @@ +# Copyright 2016-2017 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 + - id: vsperf type: group role: [vsperf] diff --git a/fuel-plugin-vsperf/environment_config.yaml b/fuel-plugin-vsperf/environment_config.yaml index e69de29b..5962e8cf 100644 --- a/fuel-plugin-vsperf/environment_config.yaml +++ b/fuel-plugin-vsperf/environment_config.yaml @@ -0,0 +1,6 @@ +# Copyright (c) 2016-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 diff --git a/fuel-plugin-vsperf/node_roles.yaml b/fuel-plugin-vsperf/node_roles.yaml index 0f4f8350..c2370fc7 100644 --- a/fuel-plugin-vsperf/node_roles.yaml +++ b/fuel-plugin-vsperf/node_roles.yaml @@ -1,3 +1,10 @@ +# Copyright (c) 2016-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + vsperf: name: "VSPERF" description: "Install VSPERF on nodes with this role" diff --git a/fuel-plugin-vsperf/pre_build_hook b/fuel-plugin-vsperf/pre_build_hook index b4da204f..ea7bc206 100755 --- a/fuel-plugin-vsperf/pre_build_hook +++ b/fuel-plugin-vsperf/pre_build_hook @@ -1,5 +1,12 @@ #!/bin/bash +# Copyright (c) 2016-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + # Add here any the actions which are required before plugin build # like packages building, packages downloading from mirrors and so on. # The script should return 0 if there were no errors. diff --git a/fuel-plugin-vsperf/tasks.yaml b/fuel-plugin-vsperf/tasks.yaml index fe51488c..c7f81214 100644 --- a/fuel-plugin-vsperf/tasks.yaml +++ b/fuel-plugin-vsperf/tasks.yaml @@ -1 +1,8 @@ +# Copyright (c) 2016-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + [] diff --git a/fuel-plugin-vsperf/vagrant/README.md b/fuel-plugin-vsperf/vagrant/README.md index fa0fd823..c979e783 100644 --- a/fuel-plugin-vsperf/vagrant/README.md +++ b/fuel-plugin-vsperf/vagrant/README.md @@ -1,3 +1,8 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + Build fuel plugin ================== diff --git a/fuel-plugin-vsperf/vagrant/Vagrantfile b/fuel-plugin-vsperf/vagrant/Vagrantfile index d83ac4cc..78128e8b 100644 --- a/fuel-plugin-vsperf/vagrant/Vagrantfile +++ b/fuel-plugin-vsperf/vagrant/Vagrantfile @@ -1,4 +1,11 @@ -# -*- mode: ruby -*- +# Copyright (c) 2016-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +# # -*- mode: ruby -*- # vi: set ft=ruby : # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! diff --git a/fuel-plugin-vsperf/vagrant/build_fuel_plugin.sh b/fuel-plugin-vsperf/vagrant/build_fuel_plugin.sh index 80fc3353..cd3e6226 100755 --- a/fuel-plugin-vsperf/vagrant/build_fuel_plugin.sh +++ b/fuel-plugin-vsperf/vagrant/build_fuel_plugin.sh @@ -1,4 +1,12 @@ #!/bin/bash + +# Copyright (c) 2016-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + sudo apt-get update -y sudo apt-get install -y ruby-dev rubygems-integration python-pip rpm createrepo dpkg-dev sudo gem install fpm diff --git a/jobs/README b/jobs/README deleted file mode 100644 index 9620ca97..00000000 --- a/jobs/README +++ /dev/null @@ -1 +0,0 @@ -This folder contains frequently used test configurations diff --git a/jobs/README.md b/jobs/README.md new file mode 100644 index 00000000..affed7cd --- /dev/null +++ b/jobs/README.md @@ -0,0 +1,6 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + +This folder contains frequently used test configurations diff --git a/onboarding.txt b/onboarding.txt index a6a7fcc1..9fa742b2 100644 --- a/onboarding.txt +++ b/onboarding.txt @@ -1,3 +1,6 @@ +# This work is licensed under a Creative Commons Attribution 4.0 International License. +# http://creativecommons.org/licenses/by/4.0 + Get on board by filling this out and submitting it for review. This is all optional, it's just to give you a taste of the workflow. diff --git a/packages.txt b/packages.txt deleted file mode 100644 index 7d68021d..00000000 --- a/packages.txt +++ /dev/null @@ -1,9 +0,0 @@ -python33-* -pciutils -gcc -zlib -zlib-devel -glib2-devel -pixman-devel -socat -sysstat @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -174,7 +174,7 @@ function-rgx=[a-z_][a-z0-9_]{2,30}$ function-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ +method-rgx=[a-z_][a-z0-9_]{2,35}$ # Naming hint for method names method-name-hint=[a-z_][a-z0-9_]{2,30}$ @@ -347,13 +347,13 @@ max-args=6 ignored-argument-names=_.* # Maximum number of locals for function / method body -max-locals=20 +max-locals=25 # Maximum number of return / yield for function / method body -max-returns=6 +max-returns=10 # Maximum number of branch for function / method body -max-branches=15 +max-branches=25 # Maximum number of statements in function / method body max-statements=70 diff --git a/requirements.txt b/requirements.txt index 5d44bbd6..8b928d4d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,15 @@ +# Copyright (c) 2015-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + pexpect==3.3 tox==1.8.1 jinja2==2.7.3 xmlrunner==1.7.7 requests==2.8.1 netaddr==0.7.18 -scapy-python3==0.18
\ No newline at end of file +scapy-python3==0.18 +distro diff --git a/src/README b/src/README.md index 0492fa1d..0aeea04f 100644 --- a/src/README +++ b/src/README.md @@ -1,3 +1,8 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + ### Purpose of this folder - Quickview 1. contains place holders for upstream source code package. diff --git a/src/dpdk/__init__.py b/src/dpdk/__init__.py index fdbc5414..7b721be0 100644 --- a/src/dpdk/__init__.py +++ b/src/dpdk/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,4 +20,3 @@ and removing drivers and binding/unbinding NICs. from src.dpdk.dpdk import * from src.dpdk.testpmd_proc import TestPMDProcess - diff --git a/src/dpdk/dpdk.py b/src/dpdk/dpdk.py index 0c5ed9f4..438fe40b 100644 --- a/src/dpdk/dpdk.py +++ b/src/dpdk/dpdk.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -44,6 +44,7 @@ _NICS_PCI = [] def init(): """Setup system for DPDK. """ + # pylint: disable=global-statement global _NICS global _NICS_PCI _NICS = S.getValue('NICS') diff --git a/src/mk/README b/src/mk/README deleted file mode 100644 index 52f83600..00000000 --- a/src/mk/README +++ /dev/null @@ -1,3 +0,0 @@ - -This folder contains top level makefile defintions - diff --git a/src/mk/README.md b/src/mk/README.md new file mode 100644 index 00000000..6d39f2b2 --- /dev/null +++ b/src/mk/README.md @@ -0,0 +1,7 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + +This folder contains top level makefile defintions + diff --git a/src/ovs/dpctl.py b/src/ovs/dpctl.py index 44a4ec9b..015fb38c 100644 --- a/src/ovs/dpctl.py +++ b/src/ovs/dpctl.py @@ -1,4 +1,4 @@ -# Copyright 2016 Intel Corporation. +# Copyright 2016-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,10 +15,7 @@ """Wrapper for an OVS dpctl (``ovs-dpctl``) for managing datapaths. """ - -import os import logging -import string from tools import tasks from conf import settings @@ -65,4 +62,3 @@ class DPCtl(object): """ self.logger.debug('delete datapath ' + dp_name) self.run_dpctl(['del-dp', dp_name]) - diff --git a/src/ovs/ofctl.py b/src/ovs/ofctl.py index e9b86127..f0d116da 100644 --- a/src/ovs/ofctl.py +++ b/src/ovs/ofctl.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 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,8 +19,6 @@ Much of this code is based on ``ovs-lib.py`` from Open Stack: https://github.com/openstack/neutron/blob/6eac1dc99124ca024d6a69b3abfa3bc69c735667/neutron/agent/linux/ovs_lib.py """ - -import os import logging import string import re @@ -177,7 +175,7 @@ class OFBridge(OFBase): :return: None """ - tmp_timeout = self.timeout if timeout == None else timeout + tmp_timeout = self.timeout if timeout is None else timeout cmd = ['sudo', settings.getValue('TOOLS')['ovs-ofctl'], '-O', 'OpenFlow13', '--timeout', str(tmp_timeout)] + args return tasks.run_task( @@ -292,7 +290,7 @@ class OFBridge(OFBase): """ # insert flows from cache into OVS if needed if cache == 'flush': - if self._cache_file == None: + if self._cache_file is None: self.logger.error('flow cache flush called, but nothing is cached') return self.logger.debug('flows cached in %s will be added to the bridge', _CACHE_FILE_NAME) @@ -311,7 +309,7 @@ class OFBridge(OFBase): # insert flow to the cache or OVS if cache == 'on': # create and open cache file if needed - if self._cache_file == None: + if self._cache_file is None: self._cache_file = open(_CACHE_FILE_NAME, 'w') self._cache_file.write(_flow_key + '\n') else: diff --git a/src/package-list.mk b/src/package-list.mk index 6eb43b8b..9334cd8e 100644 --- a/src/package-list.mk +++ b/src/package-list.mk @@ -1,3 +1,10 @@ +# Copyright (c) 2016-2017 Intel corporation. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +# # Upstream Package List # # Everything here is defined as its suggested default diff --git a/systems/README b/systems/README.md index 14967107..d72aae65 100644 --- a/systems/README +++ b/systems/README.md @@ -1,3 +1,8 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + This folder abstract out details among linux distros. One time setup: diff --git a/systems/fedora/20/build_base_machine.sh b/systems/fedora/20/build_base_machine.sh deleted file mode 100755 index 839d2bee..00000000 --- a/systems/fedora/20/build_base_machine.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash -# -# Build a base machine for Fedora distro -# -# Copyright 2015 OPNFV, 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. -# -# Contributors: -# Aihua Li, Huawei Technologies. -# Martin Klozik, Intel Corporation. -# Abdul Halim, Intel Corporation. - -yum -y install $(echo " -# Make and Compilers -make -automake -gcc -gcc-c++ -libxml2 -glibc -glib2-devel -kernel-devel -fuse-libs -fuse -fuse-devel - -# tools -curl -autoconf -libtool -libpcap-devel -libnet -vim -wget -git -pciutils -cifs-utils -socat - -# install python packages -python3 -python3-virtualenv -python3-setuptools -python3-pip -python3-dbus -python3-devel -python3-tkinter -systemd-python3 -python3-libs -libreport-python3 -abrt-python3 -abrt-addon-python3 - -# libs -numactl -numactl-devel - -# install git-review tool -git-review -" | grep -v ^#) diff --git a/systems/fedora/21/build_base_machine.sh b/systems/fedora/21/build_base_machine.sh deleted file mode 100755 index e4969893..00000000 --- a/systems/fedora/21/build_base_machine.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/bash -# -# Build a base machine for Fedora distro -# -# Copyright 2015 OPNFV, 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. -# -# Contributors: -# Aihua Li, Huawei Technologies. -# Martin Klozik, Intel Corporation. -# Abdul Halim, Intel Corporation. - -yum -y install $(echo " -# Make and Compilers -make -automake -gcc -gcc-c++ -libxml2 -glibc -glib2-devel -kernel-devel -fuse-libs -fuse -fuse-devel -kernel-modules-extra -pixman-devel -openssl-devel - -# tools -curl -autoconf -libtool -libpcap-devel -libnet -vim -wget -git -pciutils -cifs-utils -socat - -# install python packages -python3 -python3-virtualenv -python3-setuptools -python3-pip -python3-dbus -python3-devel -python3-tkinter -systemd-python3 -python3-libs -libreport-python3 -abrt-python3 -abrt-addon-python3 - -# libs -numactl -numactl-devel - -# install git-review tool -git-review -" | grep -v ^#) || exit 1 - -# Create hugepage dirs -mkdir -p /dev/hugepages diff --git a/systems/fedora/21/prepare_python_env.sh b/systems/fedora/21/prepare_python_env.sh deleted file mode 100755 index f348c75d..00000000 --- a/systems/fedora/21/prepare_python_env.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -# -# Prepare Python environment for vsperf execution on Fedora systems -# -# Copyright 2015 OPNFV, 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. - -if [ -d "$VSPERFENV_DIR" ] ; then - echo "Directory $VSPERFENV_DIR already exists. Skipping python virtualenv creation." - exit -fi - -# enable virtual environment in a subshell, so QEMU build can use python 2.7 - -(virtualenv-3.4 "$VSPERFENV_DIR" || exit 1 -source "$VSPERFENV_DIR"/bin/activate || exit 1 -pip install -r ../requirements.txt || exit 1 -pip install pylint || exit 1) diff --git a/systems/fedora/22/build_base_machine.sh b/systems/fedora/25/build_base_machine.sh index 3cfe0c78..ad53ba76 100755..100644 --- a/systems/fedora/22/build_base_machine.sh +++ b/systems/fedora/25/build_base_machine.sh @@ -1,8 +1,8 @@ #!/bin/bash # -# Build a base machine for Fedora 22 +# Build a base machine for Fedora 25 # -# Copyright 2015 OPNFV, Intel Corporation. +# Copyright 2017 OPNFV, Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,11 +15,6 @@ # 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. -# -# Contributors: -# Aihua Li, Huawei Technologies. -# Martin Klozik, Intel Corporation. -# Abdul Halim, Intel Corporation. dnf -y install $(echo " # Make and Compilers diff --git a/systems/fedora/22/prepare_python_env.sh b/systems/fedora/25/prepare_python_env.sh index 0b2c5a32..4a85eb35 100755..100644 --- a/systems/fedora/22/prepare_python_env.sh +++ b/systems/fedora/25/prepare_python_env.sh @@ -1,8 +1,8 @@ #!/bin/bash # -# Prepare Python environment for vsperf execution on Fedora 22 systems. +# Prepare Python environment for vsperf execution on Fedora 25 systems. # -# Copyright 2015 OPNFV, Intel Corporation. +# Copyright 2017 OPNFV, Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -23,7 +23,8 @@ fi # enable virtual environment in a subshell, so QEMU build can use python 2.7 -(virtualenv-3.4 "$VSPERFENV_DIR" +(virtualenv-3.5 "$VSPERFENV_DIR" source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint)
\ No newline at end of file +pip install pylint +pip install six) diff --git a/systems/opensuse/42.2/build_base_machine.sh b/systems/opensuse/42.2/build_base_machine.sh new file mode 100755 index 00000000..cf55484b --- /dev/null +++ b/systems/opensuse/42.2/build_base_machine.sh @@ -0,0 +1,93 @@ +#!/bin/bash +# +# Build a base machine for openSUSE Leap 42.2 systems +# +# Copyright (c) 2017 SUSE LLC. +# +# 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. +# +# Contributors: +# Marco Varlese, SUSE LINUX GmbH + +zypper update +zypper install $(echo " +# compiler, tools and dependencies +make +automake +gcc +gcc-c++ +glibc +glibc-devel +fuse +fuse-devel +glib2-devel +zlib-devel +ncurses-devel +kernel-default +kernel-default-devel +pkg-config +findutils-locate +curl +automake +autoconf +vim +wget +git +pciutils +cifs-utils +socat +sysstat +java-1_8_0-openjdk +git-review + +# python +python3 +python-pip +python3-pip +python3-setuptools +python3-devel +python3-tk + +# libraries +libnuma1 +libnuma-devel +libpixman-1-0 +libpixman-1-0-devel +libtool +libpcap-devel +libnet9 +libncurses5 +libcurl4 +libcurl-devel +libxml2 +libfuse2 +libopenssl1_0_0 +libopenssl-devel +libpython3_4m1_0 + +" | grep -v ^#) + +updatedb + +# fix for the Ixia TclClient +ln -sf $(locate libc.so.6) /lib/libc.so.6 + +# virtual environment for python +pip3 install virtualenv + +# hugepages setup +mkdir -p /dev/hugepages + +# fix for non-utf8 characters in file +cp /etc/services /etc/services.bak +iconv -o /etc/services -f utf-8 -t utf-8 -c /etc/services.bak diff --git a/systems/fedora/20/prepare_python_env.sh b/systems/opensuse/42.2/prepare_python_env.sh index d0efd687..66f94cf7 100755 --- a/systems/fedora/20/prepare_python_env.sh +++ b/systems/opensuse/42.2/prepare_python_env.sh @@ -1,8 +1,8 @@ #!/bin/bash # -# Prepare Python environment for vsperf execution on Fedora systems +# Prepare Python environment for vsperf execution on openSUSE Leap 42.2 systems # -# Copyright 2015 OPNFV, Intel Corporation. +# Copyright (c) 2017 SUSE LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,9 +21,8 @@ if [ -d "$VSPERFENV_DIR" ] ; then exit fi -# enable virtual environment in a subshell, so QEMU build can use python 2.7 - -(virtualenv-3.3 "$VSPERFENV_DIR" +virtualenv "$VSPERFENV_DIR" source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint) +pip install pylint + diff --git a/testcases/README b/testcases/README.md index be6ffae2..9a1eec49 100644 --- a/testcases/README +++ b/testcases/README.md @@ -1,3 +1,8 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + ### This folder contains various test cases for performance test. * P2P: packets flow from PHY -> vSwitch -> PHY diff --git a/testcases/performance.py b/testcases/performance.py index 240d04a9..0be99724 100644 --- a/testcases/performance.py +++ b/testcases/performance.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ import logging from testcases import TestCase from tools.report import report -from conf import settings as S class PerformanceTestCase(TestCase): """PerformanceTestCase class diff --git a/testcases/testcase.py b/testcases/testcase.py index 425581b7..4fbf9c04 100644 --- a/testcases/testcase.py +++ b/testcases/testcase.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -38,11 +38,13 @@ from tools.teststepstools import TestStepsTools CHECK_PREFIX = 'validate_' +# pylint: disable=too-many-instance-attributes class TestCase(object): """TestCase base class In this basic form runs RFC2544 throughput test """ + # pylint: disable=too-many-statements def __init__(self, cfg): """Pull out fields from test config @@ -138,7 +140,7 @@ class TestCase(object): 'tunnel_type': self._tunnel_type,}) # Packet Forwarding mode - self._vswitch_none = 'none' == S.getValue('VSWITCH').strip().lower() + self._vswitch_none = S.getValue('VSWITCH').strip().lower() == 'none' # trafficgen configuration required for tests of tunneling protocols if self.deployment == "op2p": @@ -255,9 +257,6 @@ class TestCase(object): # umount hugepages if mounted self._umount_hugepages() - # restore original settings - S.load_from_dict(self._settings_original) - # cleanup any namespaces created if os.path.isdir('/tmp/namespaces'): namespace_list = os.listdir('/tmp/namespaces') @@ -331,6 +330,9 @@ class TestCase(object): # report test results self.run_report() + # restore original settings + S.load_from_dict(self._settings_original) + def _update_settings(self, param, value): """ Check value of given configuration parameter In case that new value is different, then testcase @@ -428,6 +430,7 @@ class TestCase(object): def _mount_hugepages(self): """Mount hugepages if usage of DPDK or Qemu is detected """ + # pylint: disable=too-many-boolean-expressions # hugepages are needed by DPDK and Qemu if not self._hugepages_mounted and \ (self.deployment.count('v') or \ @@ -457,26 +460,11 @@ class TestCase(object): # 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( - r'-socket-mem\s+(\d+),(\d+)', - ''.join(S.getValue('VSWITCHD_DPDK_ARGS'))) - if match: - sock0_mem, sock1_mem = (int(match.group(1)) * 1024 / hugepage_size, - int(match.group(2)) * 1024 / hugepage_size) - 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 / hugepage_size, - int(sock1_mem) * 1024 / hugepage_size) + sock_mem = S.getValue('DPDK_SOCKET_MEM') + sock0_mem, sock1_mem = (int(sock_mem[0]) * 1024 / hugepage_size, + int(sock_mem[1]) * 1024 / hugepage_size) # If hugepages needed, verify the amounts are free if any([hugepages_needed, sock0_mem, sock1_mem]): @@ -505,8 +493,8 @@ class TestCase(object): else: result3 = True - logging.info('Need a total of {} total hugepages'.format( - hugepages_needed + sock1_mem + sock0_mem)) + logging.info('Need a total of %s total hugepages', + 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 @@ -561,7 +549,7 @@ class TestCase(object): """Add flows to the vswitch """ vswitch = self._vswitch_ctl.get_vswitch() - # TODO BOM 15-08-07 the frame mod code assumes that the + # NOTE BOM 15-08-07 the frame mod code assumes that the # physical ports are ports 1 & 2. The actual numbers # need to be retrived from the vSwitch and the metadata value # updated accordingly. @@ -627,7 +615,7 @@ class TestCase(object): 'goto_table:3']} vswitch.add_flow(bridge, flow) elif self._frame_mod == "ip_port": - # TODO BOM 15-08-27 The traffic generated is assumed + # NOTE BOM 15-08-27 The traffic generated is assumed # to be UDP (nw_proto 17d) which is the default case but # we will need to pick up the actual traffic params in use. flow = {'table':'2', 'priority':'1000', 'metadata':'2', @@ -711,6 +699,9 @@ class TestCase(object): # initialize list with results self._step_result = [None] * len(self.test) + # We have to suppress pylint report, because test_object has to be set according + # to the test step definition + # pylint: disable=redefined-variable-type # run test step by step... for i, step in enumerate(self.test): step_ok = not self._step_check diff --git a/tools/README b/tools/README deleted file mode 100644 index a10c2bb3..00000000 --- a/tools/README +++ /dev/null @@ -1 +0,0 @@ -This folder contains various tool sets for vswitch performance diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 00000000..dc00eac8 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,6 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + +This folder contains various tool sets for vswitch performance diff --git a/tools/collectors/sysmetrics/pidstat.py b/tools/collectors/sysmetrics/pidstat.py index 5106697e..99341ccf 100644 --- a/tools/collectors/sysmetrics/pidstat.py +++ b/tools/collectors/sysmetrics/pidstat.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -42,8 +42,8 @@ import time from collections import OrderedDict from tools import tasks from tools import systeminfo -from conf import settings from tools.collectors.collector import collector +from conf import settings _ROOT_DIR = os.path.dirname(os.path.realpath(__file__)) diff --git a/tools/functions.py b/tools/functions.py index 3bd8cc4d..d00200d9 100644 --- a/tools/functions.py +++ b/tools/functions.py @@ -1,4 +1,4 @@ -# Copyright 2016 Intel Corporation. +# Copyright 2016-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ from conf import settings as S # # Support functions # - +# pylint: disable=too-many-branches def settings_update_paths(): """ Configure paths to OVS, DPDK and QEMU sources and binaries based on selected vswitch type and src/binary switch. Data are taken from @@ -74,6 +74,7 @@ def settings_update_paths(): paths['paths']['ovs_etc_tmp'] = S.getValue('PATHS')['vswitch']['ovs_etc_tmp'] tools = {} + # pylint: disable=too-many-nested-blocks for path_class in paths: for tool in paths[path_class]: tmp_tool = paths[path_class][tool] @@ -123,8 +124,8 @@ def settings_update_paths(): tmp_tool = tmp_glob[0] elif not os.path.exists(tmp_tool): if tool.endswith('_tmp'): - logging.getLogger().debug('Temporary path to the {} does not ' - 'exist: {}.'.format(tool, tmp_tool)) + logging.getLogger().debug('Temporary path to the %s does not ' + 'exist: %s', tool, tmp_tool) else: raise RuntimeError('Path to the {} is not valid: {}'.format(tool, tmp_tool)) diff --git a/tools/hugepages.py b/tools/hugepages.py index d233f04d..4c91e7d2 100644 --- a/tools/hugepages.py +++ b/tools/hugepages.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ from tools import tasks from conf import settings _LOGGER = logging.getLogger(__name__) -_allocated_hugepages = False +_ALLOCATED_HUGEPAGES = False # # hugepage management # @@ -37,16 +37,15 @@ def get_hugepage_size(): """ 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() + with open('/proc/meminfo', 'r') as result_file: + data = result_file.readlines() for line in data: match = hugepage_size_re.search(line) if match: _LOGGER.info('Hugepages size: %s kb', match.group('size_hp')) return int(match.group('size_hp')) - else: - _LOGGER.error('Could not parse for hugepage size') - return 0 + _LOGGER.error('Could not parse for hugepage size') + return 0 def allocate_hugepages(): @@ -54,19 +53,20 @@ def allocate_hugepages(): """ 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 - global _allocated_hugepages - _allocated_hugepages = True - return True + 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 + # pylint: disable=global-statement + global _ALLOCATED_HUGEPAGES + _ALLOCATED_HUGEPAGES = True + return True else: _LOGGER.error('Division by 0 will be supported in next release') @@ -75,8 +75,9 @@ def allocate_hugepages(): def deallocate_hugepages(): """De-allocate hugepages that were allocated on the fly """ - global _allocated_hugepages - if _allocated_hugepages: + # pylint: disable=global-statement + global _ALLOCATED_HUGEPAGES + if _ALLOCATED_HUGEPAGES: nr_hugepages = 'vm.nr_hugepages= 0' try: tasks.run_task(['sudo', 'sysctl', nr_hugepages], @@ -84,7 +85,7 @@ def deallocate_hugepages(): except subprocess.CalledProcessError: _LOGGER.error('Unable to de-allocate hugepages.') return False - _allocated_hugepages = False + _ALLOCATED_HUGEPAGES = False return True @@ -102,22 +103,21 @@ def get_free_hugepages(socket=None): meminfo_path = '/sys/devices/system/node/node{}/meminfo'.format( socket) else: - _LOGGER.info('No hugepage info found for socket {}'.format(socket)) + _LOGGER.info('No hugepage info found for socket %s', socket) return 0 else: meminfo_path = '/proc/meminfo' - with open(meminfo_path, 'r') as fh: - data = fh.readlines() + with open(meminfo_path, 'r') as result_file: + data = result_file.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 + _LOGGER.info('Could not parse for hugepage size') + return 0 def is_hugepage_available(): diff --git a/tools/load_gen/dummy/dummy.py b/tools/load_gen/dummy/dummy.py index 1ad6c3fd..91bef4fa 100644 --- a/tools/load_gen/dummy/dummy.py +++ b/tools/load_gen/dummy/dummy.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ from tools.load_gen.load_gen import ILoadGenerator +# pylint: disable=super-init-not-called class DummyLoadGen(ILoadGenerator): """Dummy load generator, which doesn't generate any load""" def __init__(self, stress_config): @@ -26,6 +27,6 @@ class DummyLoadGen(ILoadGenerator): """Start stress load if it was requested""" pass - def kill(self, signal='-15', sleep=2): + def kill(self, dummy_signal='-15', dummy_sleep=2): """Kill stress load if it is active""" pass diff --git a/tools/module_manager.py b/tools/module_manager.py index 911f7252..dd1d92be 100644 --- a/tools/module_manager.py +++ b/tools/module_manager.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -143,8 +143,7 @@ class ModuleManager(object): return None - @staticmethod - def get_module_dependecies(module): + def get_module_dependecies(self, module): """Return list of modules, which must be loaded before module itself :param module: a name of kernel module diff --git a/tools/networkcard.py b/tools/networkcard.py index 945534be..2cd296fb 100644 --- a/tools/networkcard.py +++ b/tools/networkcard.py @@ -1,4 +1,4 @@ -# Copyright 2016 Intel Corporation. +# Copyright 2016-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -263,4 +263,3 @@ def reinit_vfs(pf_pci_handle): _LOGGER.warning('Error during reinitialization of VF %s', vf_nic) else: _LOGGER.warning("Can't detect driver for VF %s", vf_nic) - diff --git a/tools/opnfvdashboard/opnfvdashboard.py b/tools/opnfvdashboard/opnfvdashboard.py index 6f53526d..3f465c04 100644 --- a/tools/opnfvdashboard/opnfvdashboard.py +++ b/tools/opnfvdashboard/opnfvdashboard.py @@ -1,7 +1,7 @@ """ vsperf2dashboard """ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,12 +15,10 @@ vsperf2dashboard # See the License for the specific language governing permissions and # limitations under the License. - import os import csv -import requests -import json import logging +import requests def results2opnfv_dashboard(results_path, int_data): """ @@ -66,7 +64,7 @@ def _push_results(reader, int_data): version_ovs = line.replace(' ', '') version_ovs = version_ovs.replace('OVS_TAG?=', '') if "DPDK_TAG" in line: - if int_data['vanilla'] == False: + if int_data['vanilla'] is False: version_dpdk = line.replace(' ', '') version_dpdk = version_dpdk.replace('DPDK_TAG?=', '') else: @@ -81,8 +79,8 @@ def _push_results(reader, int_data): "version": version, "details": details} - myData = requests.post(url, json=body) - logging.info("Results for %s sent to opnfv, http response: %s", casename, myData) + my_data = requests.post(url, json=body) + logging.info("Results for %s sent to opnfv, http response: %s", casename, my_data) logging.debug("opnfv url: %s", db_url) logging.debug("the body sent to opnfv") logging.debug(body) @@ -111,7 +109,7 @@ def _generate_test_name(testcase, int_data): for name, name_list in names.items(): if name != testcase: continue - if vanilla == True: + if vanilla is True: res_name = name_list[1] else: res_name = name_list[0] diff --git a/tools/pkt_fwd/pkt_fwd.py b/tools/pkt_fwd/pkt_fwd.py index a080b5a2..b0423b7b 100644 --- a/tools/pkt_fwd/pkt_fwd.py +++ b/tools/pkt_fwd/pkt_fwd.py @@ -1,4 +1,4 @@ -# Copyright 2016 Intel Corporation. +# Copyright 2016-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -56,4 +56,3 @@ class IPktFwd(object): :returns: None """ raise NotImplementedError('Please call an implementation.') - diff --git a/tools/pkt_fwd/testpmd.py b/tools/pkt_fwd/testpmd.py index 30e80386..970259dc 100644 --- a/tools/pkt_fwd/testpmd.py +++ b/tools/pkt_fwd/testpmd.py @@ -1,4 +1,4 @@ -# Copyright 2016 Intel Corporation. +# Copyright 2016-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -41,6 +41,14 @@ class TestPMD(IPktFwd): def __init__(self, guest=False): vswitchd_args = settings.getValue('VSWITCHD_DPDK_ARGS') + + # override socket-mem settings + for tmp_arg in vswitchd_args: + if tmp_arg.startswith('--socket-mem'): + vswitchd_args.remove(tmp_arg) + vswitchd_args += ['--socket-mem ' + + ','.join(settings.getValue('DPDK_SOCKET_MEM'))] + if guest: vswitchd_args += _TESTPMD_PVP_CONST_ARGS vswitchd_args += _VSWITCHD_CONST_ARGS @@ -100,5 +108,3 @@ class TestPMD(IPktFwd): except pexpect.EOF: pass dpdk.cleanup() - - diff --git a/tools/pkt_gen/dummy/dummy.py b/tools/pkt_gen/dummy/dummy.py index 7a4daab6..3dc5448e 100755 --- a/tools/pkt_gen/dummy/dummy.py +++ b/tools/pkt_gen/dummy/dummy.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -59,7 +59,6 @@ def _get_user_traffic_stat(stat_type): else: print('Please respond with \'yes\' or \'no\' ', end='') - def get_user_traffic(traffic_type, traffic_conf, flow_conf, traffic_stats): """ Request user input for traffic. @@ -229,15 +228,36 @@ class Dummy(trafficgen.ITrafficGenerator): traffic_, ('b2b frames', 'b2b frame loss %')) - framesize = traffic_['l2']['framesize'] - # builds results by using user-supplied values # and guessing remainder using available info result[ResultsConstants.B2B_FRAMES] = float(results[0]) result[ResultsConstants.B2B_FRAME_LOSS_PERCENT] = float(results[1]) return result + def start_cont_traffic(self, traffic=None, duration=20): + return NotImplementedError('Dummy does not implement start_cont_traffic') + + def stop_cont_traffic(self): + return NotImplementedError( + 'Dummy does not implement stop_cont_traffic') + + def start_rfc2544_back2back(self, traffic=None, tests=1, duration=20, + lossrate=0.0): + return NotImplementedError( + 'Dummy does not implement start_rfc2544_back2back') + + def wait_rfc2544_back2back(self): + return NotImplementedError( + 'Dummy does not implement stop_cont_traffic') + + def start_rfc2544_throughput(self, traffic=None, tests=1, duration=20, + lossrate=0.0): + return NotImplementedError( + 'Dummy does not implement start_rfc2544_throughput') + def wait_rfc2544_throughput(self): + return NotImplementedError( + 'Dummy does not implement wait_rfc2544_throughput') if __name__ == '__main__': TRAFFIC = { diff --git a/tools/pkt_gen/ixia/ixia.py b/tools/pkt_gen/ixia/ixia.py index ed947e70..13c1a9a7 100755 --- a/tools/pkt_gen/ixia/ixia.py +++ b/tools/pkt_gen/ixia/ixia.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -33,7 +33,6 @@ This requires the following settings in your config file: If any of these don't exist, the application will raise an exception (EAFP). """ - import tkinter import logging import os @@ -106,9 +105,7 @@ def _build_set_cmds(values, prefix='dict set'): for key in values: value = values[key] - # Not allowing derived dictionary types for now - # pylint: disable=unidiomatic-typecheck - if type(value) == dict: + if isinstance(value, dict): _prefix = ' '.join([prefix, key]).strip() for subkey in _build_set_cmds(value, _prefix): yield subkey @@ -116,7 +113,7 @@ def _build_set_cmds(values, prefix='dict set'): # tcl doesn't recognise the strings "True" or "False", only "1" # or "0". Special case to convert them - if type(value) == bool: + if isinstance(value, bool): value = str(int(value)) else: value = str(value) @@ -138,6 +135,29 @@ class Ixia(trafficgen.ITrafficGenerator): _tclsh = tkinter.Tcl() _logger = logging.getLogger(__name__) + def start_rfc2544_throughput(self, traffic=None, tests=1, duration=20, + lossrate=0.0): + return NotImplementedError( + 'Ixia start throughput traffic not implemented') + + def wait_rfc2544_throughput(self): + return NotImplementedError( + 'Ixia wait throughput traffic not implemented') + + def start_rfc2544_back2back(self, traffic=None, tests=1, duration=20, + lossrate=0.0): + return NotImplementedError( + 'Ixia start back2back traffic not implemented') + + def send_rfc2544_back2back(self, traffic=None, duration=60, + lossrate=0.0, tests=1): + return NotImplementedError( + 'Ixia send back2back traffic not implemented') + + def wait_rfc2544_back2back(self): + return NotImplementedError( + 'Ixia wait back2back traffic not implemented') + def run_tcl(self, cmd): """Run a TCL script using the TCL interpreter found in ``tkinter``. @@ -228,7 +248,7 @@ class Ixia(trafficgen.ITrafficGenerator): assert len(result) == 6 # fail-fast if underlying Tcl code changes - #TODO - implement Burst results setting via TrafficgenResults. + #NOTE - implement Burst results setting via TrafficgenResults. def send_cont_traffic(self, traffic=None, duration=30): """See ITrafficGenerator for description diff --git a/tools/pkt_gen/ixnet/ixnet.py b/tools/pkt_gen/ixnet/ixnet.py index f84ab668..9a763104 100755 --- a/tools/pkt_gen/ixnet/ixnet.py +++ b/tools/pkt_gen/ixnet/ixnet.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -78,7 +78,6 @@ does not give any feedback as to the status of tests. As such, it can be expected that the user have access to the IxNetwork machine should this trafficgen need to be debugged. """ - import tkinter import logging import os @@ -122,18 +121,15 @@ def _build_set_cmds(values, prefix='dict set'): for key in values: value = values[key] - # Not allowing derived dictionary types for now - # pylint: disable=unidiomatic-typecheck - if type(value) == dict: + if isinstance(value, dict): _prefix = ' '.join([prefix, key]).strip() for subkey in _build_set_cmds(value, _prefix): yield subkey continue - # pylint: disable=unidiomatic-typecheck # tcl doesn't recognise the strings "True" or "False", only "1" # or "0". Special case to convert them - if type(value) == bool: + if isinstance(value, bool): value = str(int(value)) else: value = str(value) @@ -511,6 +507,8 @@ class IxNet(trafficgen.ITrafficGenerator): return parse_ixnet_rfc_results(parse_result_string(output[0])) + def send_burst_traffic(self, traffic=None, numpkts=100, duration=20): + return NotImplementedError('IxNet does not implement send_burst_traffic') if __name__ == '__main__': TRAFFIC = { diff --git a/tools/pkt_gen/testcenter/testcenter-rfc2544-rest.py b/tools/pkt_gen/testcenter/testcenter-rfc2544-rest.py index 8da8ed17..6c30b130 100644 --- a/tools/pkt_gen/testcenter/testcenter-rfc2544-rest.py +++ b/tools/pkt_gen/testcenter/testcenter-rfc2544-rest.py @@ -1,4 +1,4 @@ -# Copyright 2016 Spirent Communications. +# Copyright 2016-2017 Spirent Communications. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,7 +11,9 @@ # 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. - +# +# Invalid name of file, must be used '_' instead '-' +# pylint: disable=invalid-name ''' @author Spirent Communications @@ -22,10 +24,9 @@ TestCenter REST APIs. This test supports Python 3.4 import argparse import logging import os -from conf import settings -logger = logging.getLogger(__name__) +_LOGGER = logging.getLogger(__name__) def create_dir(path): @@ -33,8 +34,8 @@ def create_dir(path): if not os.path.exists(path): try: os.makedirs(path) - except OSError as e: - logger.error("Failed to create directory %s: %s", path, str(e)) + except OSError as ex: + _LOGGER.error("Failed to create directory %s: %s", path, str(ex)) raise @@ -43,11 +44,11 @@ def write_query_results_to_csv(results_path, csv_results_file_prefix, """ Write the results of the query to the CSV """ create_dir(results_path) filec = os.path.join(results_path, csv_results_file_prefix + ".csv") - with open(filec, "wb") as f: - f.write(query_results["Columns"].replace(" ", ",") + "\n") + with open(filec, "wb") as result_file: + result_file.write(query_results["Columns"].replace(" ", ",") + "\n") for row in (query_results["Output"].replace("} {", ","). replace("{", "").replace("}", "").split(",")): - f.write(row.replace(" ", ",") + "\n") + result_file.write(row.replace(" ", ",") + "\n") def positive_int(value): @@ -67,7 +68,7 @@ def percent_float(value): "%s not in range [0.0, 100.0]" % pvalue) return pvalue - +# pylint: disable=too-many-branches, too-many-statements def main(): """ Read the arguments, Invoke Test and Return the results""" parser = argparse.ArgumentParser() @@ -142,7 +143,7 @@ def main(): dest="test_user_name") optional_named.add_argument("--results_dir", required=False, - default=settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), + default="./Results", help="The directory to copy results to", dest="results_dir") optional_named.add_argument("--csv_results_file_prefix", @@ -278,12 +279,12 @@ def main(): args = parser.parse_args() if args.verbose: - logger.debug("Creating results directory") + _LOGGER.debug("Creating results directory") create_dir(args.results_dir) session_name = args.test_session_name user_name = args.test_user_name - + # pylint: disable=import-error try: # Load Spirent REST Library from stcrestclient import stchttp @@ -291,8 +292,8 @@ def main(): stc = stchttp.StcHttp(args.lab_server_addr) session_id = stc.new_session(user_name, session_name) stc.join_session(session_id) - except RuntimeError as e: - logger.error(e) + except RuntimeError as err: + _LOGGER.error(err) raise # Get STC system info. @@ -305,43 +306,43 @@ def main(): # Retrieve and display the server information if args.verbose: - logger.debug("SpirentTestCenter system version: %s", - stc.get("system1", "version")) + _LOGGER.debug("SpirentTestCenter system version: %s", + stc.get("system1", "version")) try: device_list = [] port_list = [] if args.verbose: - logger.debug("Bring up license server") + _LOGGER.debug("Bring up license server") license_mgr = stc.get("system1", "children-licenseservermanager") if args.verbose: - logger.debug("license_mgr = %s", license_mgr) + _LOGGER.debug("license_mgr = %s", license_mgr) stc.create("LicenseServer", under=license_mgr, attributes={ - "server": args.license_server_addr}) + "server": args.license_server_addr}) # Create the root project object if args.verbose: - logger.debug("Creating project ...") + _LOGGER.debug("Creating project ...") project = stc.get("System1", "children-Project") # Configure any custom traffic parameters if args.traffic_custom == "cont": if args.verbose: - logger.debug("Configure Continuous Traffic") + _LOGGER.debug("Configure Continuous Traffic") stc.create("ContinuousTestConfig", under=project) # Create ports if args.verbose: - logger.debug("Creating ports ...") + _LOGGER.debug("Creating ports ...") east_chassis_port = stc.create('port', project) if args.verbose: - logger.debug("Configuring TX port ...") + _LOGGER.debug("Configuring TX port ...") stc.config(east_chassis_port, {'location': tx_port_loc}) port_list.append(east_chassis_port) west_chassis_port = stc.create('port', project) if args.verbose: - logger.debug("Configuring RX port ...") + _LOGGER.debug("Configuring RX port ...") stc.config(west_chassis_port, {'location': rx_port_loc}) port_list.append(west_chassis_port) @@ -387,12 +388,12 @@ def main(): # Append to the device list device_list.append(device_gen_config['ReturnList']) if args.verbose: - logger.debug(device_list) + _LOGGER.debug(device_list) # Create the RFC 2544 'metric test if args.metric == "throughput": if args.verbose: - logger.debug("Set up the RFC2544 throughput test...") + _LOGGER.debug("Set up the RFC2544 throughput test...") stc.perform("Rfc2544SetupThroughputTestCommand", params={"AcceptableFrameLoss": args.acceptable_frame_loss_pct, @@ -463,26 +464,26 @@ def main(): "system1.project", "children-port"), "autoConnect": "TRUE"}) # Apply configuration. if args.verbose: - logger.debug("Apply configuration...") + _LOGGER.debug("Apply configuration...") stc.apply() if args.verbose: - logger.debug("Starting the sequencer...") + _LOGGER.debug("Starting the sequencer...") stc.perform("SequencerStart") # Wait for sequencer to finish - logger.info( + _LOGGER.info( "Starting test... Please wait for the test to complete...") stc.wait_until_complete() - logger.info("The test has completed... Saving results...") + _LOGGER.info("The test has completed... Saving results...") # Determine what the results database filename is... lab_server_resultsdb = stc.get( "system1.project.TestResultSetting", "CurrentResultFileName") if args.verbose: - logger.debug("The lab server results database is %s", - lab_server_resultsdb) + _LOGGER.debug("The lab server results database is %s", + lab_server_resultsdb) stc.perform("CSSynchronizeFiles", params={"DefaultDownloadDir": args.results_dir}) @@ -492,10 +493,10 @@ def main(): if not os.path.exists(resultsdb): resultsdb = lab_server_resultsdb - logger.info("Failed to create the local summary DB File, using" - " the remote DB file instead.") + _LOGGER.info("Failed to create the local summary DB File, using" + " the remote DB file instead.") else: - logger.info( + _LOGGER.info( "The local summary DB file has been saved to %s", resultsdb) # The returns the "RFC2544ThroughputTestResultDetailedSummaryView" @@ -551,26 +552,26 @@ def main(): ("RFC2544FrameLossTestResultDetailed" "SummaryView")})) if args.verbose: - logger.debug("resultsdict[\"Columns\"]: %s", - resultsdict["Columns"]) - logger.debug("resultsdict[\"Output\"]: %s", resultsdict["Output"]) - logger.debug("Result paths: %s", - stc.perform("GetTestResultSettingPaths")) + _LOGGER.debug("resultsdict[\"Columns\"]: %s", + resultsdict["Columns"]) + _LOGGER.debug("resultsdict[\"Output\"]: %s", resultsdict["Output"]) + _LOGGER.debug("Result paths: %s", + stc.perform("GetTestResultSettingPaths")) # Write results to csv - logger.debug("Writing CSV file to results directory %s", - args.results_dir) + _LOGGER.debug("Writing CSV file to results directory %s", + args.results_dir) write_query_results_to_csv( args.results_dir, args.csv_results_file_prefix, resultsdict) except RuntimeError as e: - logger.error(e) + _LOGGER.error(e) if args.verbose: - logger.debug("Destroy session on lab server") + _LOGGER.debug("Destroy session on lab server") stc.end_session() - logger.info("Test complete!") + _LOGGER.info("Test complete!") if __name__ == "__main__": main() diff --git a/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py b/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py index ddb64562..044fb67d 100644 --- a/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py +++ b/tools/pkt_gen/testcenter/testcenter-rfc2889-rest.py @@ -1,4 +1,4 @@ -# Copyright 2016 Spirent Communications. +# Copyright 2016-2017 Spirent Communications. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,11 +11,11 @@ # 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. - +# pylint: disable=invalid-name ''' @author Spirent Communications -This test automates the RFC2544 tests using the Spirent +This test automates the RFC2889 tests using the Spirent TestCenter REST APIs. This test supports Python 3.4 ''' @@ -66,7 +66,7 @@ def percent_float(value): "%s not in range [0.0, 100.0]" % pvalue) return pvalue - +# pylint: disable=too-many-statements def main(): """ Read the arguments, Invoke Test and Return the results""" parser = argparse.ArgumentParser() @@ -92,9 +92,9 @@ def main(): optional_named.add_argument("--metric", required=False, help=("One among - Forwarding,\ - Address Caching and Congestion"), + Address Caching and Learning"), choices=["forwarding", "caching", - "congestion"], + "learning"], default="forwarding", dest="metric") optional_named.add_argument("--test_session_name", @@ -103,7 +103,6 @@ def main(): help=("The friendly name to identify " "the Spirent Lab Server test session"), dest="test_session_name") - optional_named.add_argument("--test_user_name", required=False, default="Rfc2889Usr", @@ -147,6 +146,42 @@ def main(): default=[256], help="A comma-delimited list of frame sizes", dest="frame_size_list") + optional_named.add_argument("--min_learning_rate", + type=positive_int, + required=False, + default=1488, + help="Lowest learning rate for test", + dest="min_learning_rate") + optional_named.add_argument("--max_learning_rate", + type=positive_int, + required=False, + default=14880, + help="Highest learning rate for test", + dest="max_learning_rate") + optional_named.add_argument("--min_num_addrs", + type=positive_int, + required=False, + default=1, + help="lowest number of addrs sent to DUT", + dest="min_num_addrs") + optional_named.add_argument("--max_num_addrs", + type=positive_int, + required=False, + default=1000, + help="Highest number of addrs sent to DUT", + dest="max_num_addrs") + optional_named.add_argument("--ac_learning_rate", + type=positive_int, + required=False, + default=1000, + help="Number of learning frames per sec", + dest="ac_learning_rate") + optional_named.add_argument("--frame_size", + type=positive_int, + required=False, + default=64, + help="Frame size for address test", + dest="frame_size") parser.add_argument("-v", "--verbose", required=False, @@ -164,6 +199,7 @@ def main(): session_name = args.test_session_name user_name = args.test_user_name + # pylint: disable=import-error try: # Load Spirent REST Library from stcrestclient import stchttp @@ -187,7 +223,7 @@ def main(): if args.verbose: logger.debug("license_mgr = %s", license_mgr) stc.create("LicenseServer", under=license_mgr, attributes={ - "server": args.license_server_addr}) + "server": args.license_server_addr}) # Create the root project object if args.verbose: @@ -224,12 +260,27 @@ def main(): "GenParams": gen_params}) if args.verbose: - logger.debug("Set up the RFC2889 Forwarding test...") - stc.perform("Rfc2889SetupMaxForwardingRateTestCommand", - params={"Duration": args.trial_duration_sec, - "FrameSizeList": args.frame_size_list, - "NumOfTrials": args.num_trials, - "TrafficPattern": args.traffic_pattern}) + logger.debug("Set up the RFC2889 test...") + + if args.metric == "learning": + stc.perform("Rfc2889SetupAddressLearningRateTestCommand", + params={"FrameSize": args.frame_size, + "MinLearningRate": args.min_learning_rate, + "MaxLearningRate": args.max_learning_rate, + "NumOfTrials": args.num_trials}) + elif args.metric == "caching": + stc.perform("Rfc2889SetupAddressCachingCapacityTestCommand", + params={"FrameSize": args.frame_size, + "MinNumAddrs": args.min_num_addrs, + "MaxNumAddrs": args.max_num_addrs, + "LearningRate": args.ac_learning_rate, + "NumOfTrials": args.num_trials}) + else: + stc.perform("Rfc2889SetupMaxForwardingRateTestCommand", + params={"Duration": args.trial_duration_sec, + "FrameSizeList": args.frame_size_list, + "NumOfTrials": args.num_trials, + "TrafficPattern": args.traffic_pattern}) # Save the configuration stc.perform("SaveToTcc", params={"Filename": "2889.tcc"}) @@ -259,28 +310,34 @@ def main(): logger.debug("The lab server results database is %s", lab_server_resultsdb) - stc.perform("CSSynchronizeFiles", - params={"DefaultDownloadDir": args.results_dir}) - - resultsdb = args.results_dir + \ - lab_server_resultsdb.split("/Results")[1] - - if not os.path.exists(resultsdb): - resultsdb = lab_server_resultsdb - logger.info("Failed to create the local summary DB file, using" - " the remote DB file instead.") + if args.metric == "learning": + resultsdict = ( + stc.perform("QueryResult", + params={ + "DatabaseConnectionString": + lab_server_resultsdb, + "ResultPath": + ("RFC2889AddressLearningRateTestResultDetailed" + "SummaryView")})) + elif args.metric == "caching": + resultsdict = ( + stc.perform("QueryResult", + params={ + "DatabaseConnectionString": + lab_server_resultsdb, + "ResultPath": + ("RFC2889AddressCachingCapacityTestResult" + "DetailedSummaryView")})) else: - logger.info( - "The local summary DB file has been saved to %s", resultsdb) - - resultsdict = ( - stc.perform("QueryResult", - params={ - "DatabaseConnectionString": - resultsdb, - "ResultPath": - ("RFC2889MaxForwardingRateTestResultDetailed" - "SummaryView")})) + resultsdict = ( + stc.perform("QueryResult", + params={ + "DatabaseConnectionString": + lab_server_resultsdb, + "ResultPath": + ("RFC2889MaxForwardingRateTestResultDetailed" + "SummaryView")})) + if args.verbose: logger.debug("resultsdict[\"Columns\"]: %s", resultsdict["Columns"]) diff --git a/tools/pkt_gen/testcenter/testcenter.py b/tools/pkt_gen/testcenter/testcenter.py index 701d451c..9980ae7c 100644 --- a/tools/pkt_gen/testcenter/testcenter.py +++ b/tools/pkt_gen/testcenter/testcenter.py @@ -115,22 +115,52 @@ def get_rfc2544_custom_settings(framesize, custom_tr, tests): return args -def get_rfc2889_settings(framesize, tests, duration): +def get_rfc2889_common_settings(framesize, tests, metric): + """ + Return RFC2889 common Settings + """ + new_metric = metric.replace('rfc2889_', '') args = [settings.getValue("TRAFFICGEN_STC_PYTHON2_PATH"), os.path.join( settings.getValue("TRAFFICGEN_STC_TESTCENTER_PATH"), settings.getValue( "TRAFFICGEN_STC_RFC2889_TEST_FILE_NAME")), - "--lab_server_addr", - settings.getValue("TRAFFICGEN_STC_LAB_SERVER_ADDR"), - "--license_server_addr", - settings.getValue("TRAFFICGEN_STC_LICENSE_SERVER_ADDR"), - "--location_list", - settings.getValue("TRAFFICGEN_STC_RFC2889_LOCATIONS"), - "--frame_size_list", - str(framesize), - "--num_trials", - str(tests)] + "--lab_server_addr", + settings.getValue("TRAFFICGEN_STC_LAB_SERVER_ADDR"), + "--license_server_addr", + settings.getValue("TRAFFICGEN_STC_LICENSE_SERVER_ADDR"), + "--location_list", + settings.getValue("TRAFFICGEN_STC_RFC2889_LOCATIONS"), + "--test_session_name", + settings.getValue("TRAFFICGEN_STC_TEST_SESSION_NAME"), + "--results_dir", + settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), + "--csv_results_file_prefix", + settings.getValue("TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX"), + "--frame_size_list", + str(framesize), + "--metric", + str(new_metric), + "--num_trials", + str(tests)] + + return args + + +def get_rfc2889_custom_settings(): + """ + Return RFC2889 Custom Settings + """ + args = ["--min_learning_rate", + settings.getValue("TRAFFICGEN_STC_RFC2889_MIN_LR"), + "--max_learning_rate", + settings.getValue("TRAFFICGEN_STC_RFC2889_MAX_LR"), + "--min_num_addrs", + settings.getValue("TRAFFICGEN_STC_RFC2889_MIN_ADDRS"), + "--max_num_addrs", + settings.getValue("TRAFFICGEN_STC_RFC2889_MAX_ADDRS"), + "--ac_learning_rate", + settings.getValue("TRAFFICGEN_STC_RFC2889_AC_LR")] return args @@ -158,19 +188,35 @@ class TestCenter(trafficgen.ITrafficGenerator): """ return None - def send_rfc2889_congestion(self, traffic=None, tests=1, duration=20): + def get_rfc2889_addr_learning_results(self, filename): """ - Do nothing. + Reads the CSV file and return the results """ - return None + result = {} + with open(filename, "r") as csvfile: + csvreader = csv.DictReader(csvfile) + for row in csvreader: + self._logger.info("Row: %s", row) + learn_rate = float(row["OptimalLearningRate"]) + result[ResultsConstants.OPTIMAL_LEARNING_RATE_FPS] = learn_rate + return result - def send_rfc2889_caching(self, traffic=None, tests=1, duration=20): + def get_rfc2889_addr_caching_results(self, filename): """ - Do nothing. + Reads the CSV file and return the results """ - return None + result = {} + with open(filename, "r") as csvfile: + csvreader = csv.DictReader(csvfile) + for row in csvreader: + self._logger.info("Row: %s", row) + caching_cap = float(row["RxFrameCount"]) + learn_per = (100.0 - (float(row["PercentFrameLoss(%)"]))) + result[ResultsConstants.CACHING_CAPACITY_ADDRS] = caching_cap + result[ResultsConstants.ADDR_LEARNED_PERCENT] = learn_per + return result - def get_rfc2889_results(self, filename): + def get_rfc2889_forwarding_results(self, filename): """ Reads the CSV file and return the results """ @@ -200,6 +246,91 @@ class TestCenter(trafficgen.ITrafficGenerator): row["ForwardingRate(fps)"]) return result + # pylint: disable=unused-argument + def send_rfc2889_forwarding(self, traffic=None, tests=1, duration=20): + """ + Send traffic per RFC2889 Forwarding test specifications. + """ + framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE") + if traffic and 'l2' in traffic: + if 'framesize' in traffic['l2']: + framesize = traffic['l2']['framesize'] + args = get_rfc2889_common_settings(framesize, tests, + traffic['traffic_type']) + if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + args.append("--verbose") + verbose = True + self._logger.debug("Arguments used to call test: %s", args) + subprocess.check_call(args) + + filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), + settings.getValue( + "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") + + ".csv") + + if verbose: + self._logger.info("file: %s", filec) + + return self.get_rfc2889_forwarding_results(filec) + + def send_rfc2889_caching(self, traffic=None, tests=1, duration=20): + """ + Send as per RFC2889 Addr-Caching test specifications. + """ + framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE") + if traffic and 'l2' in traffic: + if 'framesize' in traffic['l2']: + framesize = traffic['l2']['framesize'] + common_args = get_rfc2889_common_settings(framesize, tests, + traffic['traffic_type']) + custom_args = get_rfc2889_custom_settings() + args = common_args + custom_args + + if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + args.append("--verbose") + verbose = True + self._logger.debug("Arguments used to call test: %s", args) + subprocess.check_call(args) + + filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), + settings.getValue( + "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") + + ".csv") + + if verbose: + self._logger.info("file: %s", filec) + + return self.get_rfc2889_addr_caching_results(filec) + + def send_rfc2889_learning(self, traffic=None, tests=1, duration=20): + """ + Send traffic per RFC2889 Addr-Learning test specifications. + """ + framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE") + if traffic and 'l2' in traffic: + if 'framesize' in traffic['l2']: + framesize = traffic['l2']['framesize'] + common_args = get_rfc2889_common_settings(framesize, tests, + traffic['traffic_type']) + custom_args = get_rfc2889_custom_settings() + args = common_args + custom_args + + if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + args.append("--verbose") + verbose = True + self._logger.debug("Arguments used to call test: %s", args) + subprocess.check_call(args) + + filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), + settings.getValue( + "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") + + ".csv") + + if verbose: + self._logger.info("file: %s", filec) + + return self.get_rfc2889_addr_learning_results(filec) + def get_rfc2544_results(self, filename): """ Reads the CSV file and return the results @@ -254,7 +385,7 @@ class TestCenter(trafficgen.ITrafficGenerator): rfc2544_common_args = get_rfc2544_common_settings() rfc2544_custom_args = get_rfc2544_custom_settings(framesize, custom, 1) - args = stc_common_args + rfc2544_common_args + rfc2544_custom_args + args = rfc2544_common_args + stc_common_args + rfc2544_custom_args if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": args.append("--verbose") @@ -272,31 +403,6 @@ class TestCenter(trafficgen.ITrafficGenerator): return self.get_rfc2544_results(filec) - def send_rfc2889_forwarding(self, traffic=None, tests=1, duration=20): - """ - Send traffic per RFC2544 throughput test specifications. - """ - framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE") - if traffic and 'l2' in traffic: - if 'framesize' in traffic['l2']: - framesize = traffic['l2']['framesize'] - args = get_rfc2889_settings(framesize, tests, duration) - if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": - args.append("--verbose") - verbose = True - self._logger.debug("Arguments used to call test: %s", args) - subprocess.check_call(args) - - filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"), - settings.getValue( - "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") + - ".csv") - - if verbose: - self._logger.debug("file: %s", filec) - - return self.get_rfc2889_results(filec) - def send_rfc2544_throughput(self, traffic=None, tests=1, duration=20, lossrate=0.0): """ @@ -312,7 +418,7 @@ class TestCenter(trafficgen.ITrafficGenerator): rfc2544_common_args = get_rfc2544_common_settings() rfc2544_custom_args = get_rfc2544_custom_settings(framesize, '', tests) - args = stc_common_args + rfc2544_common_args + rfc2544_custom_args + args = rfc2544_common_args + stc_common_args + rfc2544_custom_args if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": args.append("--verbose") @@ -345,7 +451,7 @@ class TestCenter(trafficgen.ITrafficGenerator): rfc2544_common_args = get_rfc2544_common_settings() rfc2544_custom_args = get_rfc2544_custom_settings(framesize, '', tests) - args = stc_common_args + rfc2544_common_args + rfc2544_custom_args + args = rfc2544_common_args + stc_common_args + rfc2544_custom_args if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": args.append("--verbose") @@ -362,6 +468,26 @@ class TestCenter(trafficgen.ITrafficGenerator): return self.get_rfc2544_results(filecs) + def start_cont_traffic(self, traffic=None, duration=30): + raise NotImplementedError('TestCenter start_cont_traffic not implement.') + + def stop_cont_traffic(self): + raise NotImplementedError('TestCenter stop_cont_traffic not implement.') + + def start_rfc2544_back2back(self, traffic=None, tests=1, duration=20, + lossrate=0.0): + raise NotImplementedError('TestCenter start_rfc2544_back2back not implement.') + + def wait_rfc2544_back2back(self): + raise NotImplementedError('TestCenter wait_rfc2544_back2back not implement.') + + def start_rfc2544_throughput(self, traffic=None, tests=1, duration=20, + lossrate=0.0): + raise NotImplementedError('TestCenter start_rfc2544_throughput not implement.') + + def wait_rfc2544_throughput(self): + raise NotImplementedError('TestCenter wait_rfc2544_throughput not implement.') + if __name__ == '__main__': TRAFFIC = { 'l3': { diff --git a/tools/pkt_gen/xena/XenaDriver.py b/tools/pkt_gen/xena/XenaDriver.py index e144514f..6e39e47a 100644 --- a/tools/pkt_gen/xena/XenaDriver.py +++ b/tools/pkt_gen/xena/XenaDriver.py @@ -1,4 +1,4 @@ -# Copyright 2016 Red Hat Inc & Xena Networks. +# Copyright 2016-2017 Red Hat Inc & Xena Networks. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ import struct import sys import threading import time - +# pylint: disable=too-many-lines # Xena Socket Commands CMD_CLEAR_RX_STATS = 'pr_clear' CMD_CLEAR_TX_STATS = 'pt_clear' @@ -371,7 +371,7 @@ class XenaManager(object): """ return self.driver.ask_verify(make_manager_command(CMD_OWNER, username)) - +# pylint: disable=too-many-public-methods class XenaPort(object): """ Xena Port emulator class @@ -537,7 +537,7 @@ class XenaPort(object): command = make_port_command(CMD_RESET, self) return self._manager.driver.ask_verify(command) - def set_port_arp_reply(self, on=True, v6=False): + def set_port_arp_reply(self, is_on=True, ipv6=False): """ Set the port arpreply value :param on: Enable or disable the arp reply on the port @@ -545,11 +545,11 @@ class XenaPort(object): :return: Boolean True if response OK, False if error """ command = make_port_command('{} {}'.format( - CMD_SET_PORT_ARP_V6_REPLY if v6 else CMD_SET_PORT_ARP_REPLY, - "on" if on else "off"), self) + CMD_SET_PORT_ARP_V6_REPLY if ipv6 else CMD_SET_PORT_ARP_REPLY, + "on" if is_on else "off"), self) return self._manager.driver.ask_verify(command) - def set_port_ping_reply(self, on=True, v6=False): + def set_port_ping_reply(self, is_on=True, ipv6=False): """ Set the port ping reply value :param on: Enable or disable the ping reply on the port @@ -557,8 +557,8 @@ class XenaPort(object): :return: Boolean True if response OK, False if error """ command = make_port_command('{} {}'.format( - CMD_SET_PORT_PING_V6_REPLY if v6 else CMD_SET_PORT_PING_REPLY, - "on" if on else "off"), self) + CMD_SET_PORT_PING_V6_REPLY if ipv6 else CMD_SET_PORT_PING_REPLY, + "on" if is_on else "off"), self) return self._manager.driver.ask_verify(command) def set_port_learning(self, interval): @@ -885,6 +885,7 @@ class XenaRXStats(object): """ return self._time + # pylint: disable=too-many-branches def parse_stats(self): """ Parse the stats from pr all command :return: Dictionary of all stats @@ -1040,7 +1041,7 @@ class XenaTXStats(object): def aggregate_stats(stat1, stat2): """ - Judge whether stat1 and stat2 both have same key, if both have same key, + 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() diff --git a/tools/pkt_gen/xena/xena.py b/tools/pkt_gen/xena/xena.py index e251c1d6..c6b26f88 100755 --- a/tools/pkt_gen/xena/xena.py +++ b/tools/pkt_gen/xena/xena.py @@ -430,10 +430,10 @@ class Xena(ITrafficGenerator): (self._params['traffic']['frame_rate'] / 100)) stream.set_packet_limit(packets) - port.set_port_arp_reply(on=True) - port.set_port_arp_reply(on=True, v6=True) - port.set_port_ping_reply(on=True) - port.set_port_ping_reply(on=True, v6=True) + port.set_port_arp_reply(is_on=True) + port.set_port_arp_reply(is_on=True, ipv6=True) + port.set_port_ping_reply(is_on=True) + port.set_port_ping_reply(is_on=True, ipv6=True) stream.set_rate_fraction( 10000 * self._params['traffic']['frame_rate']) diff --git a/tools/pkt_gen/xena/xena_json.py b/tools/pkt_gen/xena/xena_json.py index 1ce7b46f..50d0e2fe 100644 --- a/tools/pkt_gen/xena/xena_json.py +++ b/tools/pkt_gen/xena/xena_json.py @@ -1,4 +1,4 @@ -# Copyright 2016 Red Hat Inc & Xena Networks. +# Copyright 2016-2017 Red Hat Inc & Xena Networks. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -232,10 +232,13 @@ class XenaJSON(object): """ self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][ 'Enabled'] = 'true' - + # pylint: disable=too-many-arguments def modify_2544_tput_options(self, initial_value, minimum_value, maximum_value, value_resolution, use_pass_threshhold, pass_threshhold): + """ + modify_2544_tput_options + """ self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][ 'RateIterationOptions']['InitialValue'] = initial_value self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][ @@ -638,4 +641,3 @@ if __name__ == "__main__": write_json_file(JSON.json_data, './testthis.x2544') JSON = XenaJSON('./testthis.x2544') print_json_report(JSON.json_data) - diff --git a/tools/report/report.jinja b/tools/report/report.jinja index c9588565..90cd43d7 100644 --- a/tools/report/report.jinja +++ b/tools/report/report.jinja @@ -1,3 +1,8 @@ +{# +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +#} + # CHARACTERIZE VSWITCH PERFORMANCE FOR TELCO NFV USE CASES LEVEL TEST REPORT ## Table of Contents diff --git a/tools/report/report.py b/tools/report/report.py index 1115f052..e2914fdf 100644 --- a/tools/report/report.py +++ b/tools/report/report.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -131,9 +131,10 @@ def generate(input_file, tc_results, tc_stats, test_type='performance'): 'tests': tests, } i = 0 + # pylint: disable=no-member for output_file in output_files: template = template_env.get_template(_TEMPLATE_FILES[i]) - output_text = template.render(template_vars) #pylint: disable=no-member + output_text = template.render(template_vars) with open(output_file, 'w') as file_: file_.write(output_text) logging.info('Test report written to "%s"', output_file) diff --git a/tools/report/report_foot.rst b/tools/report/report_foot.rst index f0e51876..5045e186 100644 --- a/tools/report/report_foot.rst +++ b/tools/report/report_foot.rst @@ -1,3 +1,6 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. + http://creativecommons.org/licenses/by/4.0 + .. _rationale: Rationale for decisions diff --git a/tools/report/report_rst.jinja b/tools/report/report_rst.jinja index 545dd493..e2cb4c83 100644 --- a/tools/report/report_rst.jinja +++ b/tools/report/report_rst.jinja @@ -1,3 +1,12 @@ +{# + Copyright (c) 2016-2017 Intel corporation. + + All rights reserved. This program and the accompanying materials + are made available under the terms of the Apache License, Version 2.0 + which accompanies this distribution, and is available at + http://www.apache.org/licenses/LICENSE-2.0 +#} + Test ID: {{ tests[0].ID }} -------------------------- diff --git a/tools/systeminfo.py b/tools/systeminfo.py index 1d193159..d515983d 100644 --- a/tools/systeminfo.py +++ b/tools/systeminfo.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import platform import subprocess import locale import re +import distro from conf import settings as S @@ -46,7 +47,7 @@ def get_os(): :returns: Return distro name as a string """ - return ' '.join(platform.dist()) + return ' '.join(distro.linux_distribution()) def get_kernel(): """Get kernel version. @@ -212,7 +213,7 @@ def get_git_tag(path): return None # This function uses long switch per purpose, so let us suppress pylint warning too-many-branches -# pylint: disable=R0912 +# pylint: disable=too-many-branches, too-many-statements def get_version(app_name): """ Get version of given application and its git tag diff --git a/tools/tasks.py b/tools/tasks.py index 9816a336..4179291f 100644 --- a/tools/tasks.py +++ b/tools/tasks.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,12 +18,12 @@ import select import subprocess import logging -import pexpect import threading import sys import os import locale import time +import pexpect from conf import settings from tools import systeminfo @@ -73,8 +73,8 @@ def run_task(cmd, logger, msg=None, check_error=False): if msg: logger.info(msg) + # pylint: disable=too-many-nested-blocks logger.debug('%s%s', CMD_PREFIX, ' '.join(cmd)) - try: proc = subprocess.Popen(map(os.path.expanduser, cmd), stdout=subprocess.PIPE, diff --git a/vnfs/qemu/qemu_pci_passthrough.py b/vnfs/qemu/qemu_pci_passthrough.py index f32f33d3..eec6d089 100644 --- a/vnfs/qemu/qemu_pci_passthrough.py +++ b/vnfs/qemu/qemu_pci_passthrough.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,10 +15,8 @@ """Automation of QEMU hypervisor with direct access to host NICs via PCI passthrough. """ - import logging import subprocess -import os from conf import settings as S from vnfs.qemu.qemu import IVnfQemu diff --git a/vnfs/vnf/vnf.py b/vnfs/vnf/vnf.py index 242fc502..759bdd66 100644 --- a/vnfs/vnf/vnf.py +++ b/vnfs/vnf/vnf.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -125,6 +125,7 @@ class IVnf(tasks.Process): self.execute(cmd) self.wait(prompt=prompt, timeout=timeout) + # pylint: disable=simplifiable-if-statement def validate_start(self, dummy_result): """ Validate call of VNF start() """ @@ -146,4 +147,3 @@ class IVnf(tasks.Process): This method is static """ IVnf._number_vnfs = 0 - @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -285,6 +285,28 @@ def check_and_set_locale(): _LOGGER.warning("Locale was not properly configured. Default values were set. Old locale: %s, New locale: %s", system_locale, locale.getdefaultlocale()) +def get_vswitch_names(rst_files): + """ Function will return a list of vSwitches detected in given ``rst_files``. + """ + vswitch_names = set() + if len(rst_files): + try: + output = subprocess.check_output(['grep', '-h', '^* vSwitch'] + rst_files).decode().splitlines() + for line in output: + match = re.search(r'^\* vSwitch: ([^,]+)', str(line)) + if match: + vswitch_names.add(match.group(1)) + + if len(vswitch_names): + return list(vswitch_names) + + except subprocess.CalledProcessError: + _LOGGER.warning('Cannot detect vSwitches used during testing.') + + # fallback to the default value + return ['vSwitch'] + + def generate_final_report(): """ Function will check if partial test results are available @@ -294,18 +316,15 @@ def generate_final_report(): path = settings.getValue('RESULTS_PATH') # check if there are any results in rst format rst_results = glob.glob(os.path.join(path, 'result*rst')) + pkt_processors = get_vswitch_names(rst_results) if len(rst_results): try: - test_report = os.path.join(path, '{}_{}'.format(settings.getValue('VSWITCH'), _TEMPLATE_RST['final'])) + test_report = os.path.join(path, '{}_{}'.format('_'.join(pkt_processors), _TEMPLATE_RST['final'])) # create report caption directly - it is not worth to execute jinja machinery - if settings.getValue('VSWITCH').lower() != 'none': - pkt_processor = Loader().get_vswitches()[settings.getValue('VSWITCH')].__doc__.strip().split('\n')[0] - else: - pkt_processor = Loader().get_pktfwds()[settings.getValue('PKTFWD')].__doc__.strip().split('\n')[0] report_caption = '{}\n{} {}\n{}\n\n'.format( '============================================================', 'Performance report for', - pkt_processor, + ', '.join(pkt_processors), '============================================================') with open(_TEMPLATE_RST['tmp'], 'w') as file_: @@ -479,7 +498,7 @@ class MockTestCase(unittest.TestCase): on how self.is_pass was set in the constructor""" self.assertTrue(self.is_pass, self.msg) - +# pylint: disable=too-many-locals, too-many-branches, too-many-statements def main(): """Main function. """ @@ -532,7 +551,7 @@ def main(): # configuration validity checks if args['vswitch']: - vswitch_none = 'none' == args['vswitch'].strip().lower() + vswitch_none = args['vswitch'].strip().lower() == 'none' if vswitch_none: settings.setValue('VSWITCH', 'none') else: @@ -642,6 +661,9 @@ def main(): sys.exit(1) # run tests + # Add pylint exception: Redefinition of test type from + # testcases.integration.IntegrationTestCase to testcases.performance.PerformanceTestCase + # pylint: disable=redefined-variable-type suite = unittest.TestSuite() for cfg in selected_tests: test_name = cfg.get('Name', '<Name not set>') @@ -652,7 +674,7 @@ def main(): test = PerformanceTestCase(cfg) test.run() suite.addTest(MockTestCase('', True, test.name)) - #pylint: disable=broad-except + # pylint: disable=broad-except except (Exception) as ex: _LOGGER.exception("Failed to run test: %s", test_name) suite.addTest(MockTestCase(str(ex), False, test_name)) diff --git a/vswitches/README b/vswitches/README deleted file mode 100644 index 5af284ec..00000000 --- a/vswitches/README +++ /dev/null @@ -1,6 +0,0 @@ -This folder contains various vswitches to be tested - -Required API for each vswitch: - add_switch - add_port - add_flow diff --git a/vswitches/README.md b/vswitches/README.md new file mode 100644 index 00000000..ea1e11fb --- /dev/null +++ b/vswitches/README.md @@ -0,0 +1,11 @@ +<!--- +This work is licensed under a Creative Commons Attribution 4.0 International License. +http://creativecommons.org/licenses/by/4.0 +--> + +This folder contains various vswitches to be tested + +Required API for each vswitch: + add_switch + add_port + add_flow diff --git a/vswitches/ovs.py b/vswitches/ovs.py index 886a98e0..b6d64fb7 100644 --- a/vswitches/ovs.py +++ b/vswitches/ovs.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -25,9 +25,10 @@ import pexpect from conf import settings from src.ovs import OFBridge, flow_key, flow_match -from tools import tasks from vswitches.vswitch import IVSwitch - +from tools import tasks +from tools.module_manager import ModuleManager +# pylint: disable=too-many-public-methods class IVSwitchOvs(IVSwitch, tasks.Process): """Open vSwitch base class implementation @@ -55,6 +56,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): self._cmd = [] self._cmd_template = ['sudo', '-E', settings.getValue('TOOLS')['ovs-vswitchd']] self._stamp = None + self._module_manager = ModuleManager() def start(self): """ Start ``ovsdb-server`` and ``ovs-vswitchd`` instance. @@ -138,7 +140,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): bridge = self._bridges[switch_name] remote_bridge = self._bridges[remote_switch_name] pcount = str(self._get_port_count('type=patch')) - # TODO ::: What if interface name longer than allowed width?? + # NOTE ::: What if interface name longer than allowed width?? local_port_name = switch_name + '-' + remote_switch_name + '-' + pcount remote_port_name = remote_switch_name + '-' + switch_name + '-' + pcount local_params = ['--', 'set', 'Interface', local_port_name, @@ -376,8 +378,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): # # validate methods required for integration testcases # - - def validate_add_switch(self, result, switch_name, params=None): + def validate_add_switch(self, dummy_result, switch_name, dummy_params=None): """Validate - Create a new logical switch with no ports """ bridge = self._bridges[switch_name] @@ -386,7 +387,9 @@ class IVSwitchOvs(IVSwitch, tasks.Process): assert re.search('Bridge ["\']?%s["\']?' % switch_name, output[0]) is not None return True - def validate_del_switch(self, result, switch_name): + # Method could be a function + # pylint: disable=no-self-use + def validate_del_switch(self, dummy_result, switch_name): """Validate removal of switch """ bridge = OFBridge('tmp') @@ -410,7 +413,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): """ return self.validate_add_phy_port(result, switch_name) - def validate_del_port(self, result, switch_name, port_name): + def validate_del_port(self, dummy_result, switch_name, port_name): """ Validate that port_name was removed from bridge. """ bridge = self._bridges[switch_name] @@ -419,11 +422,12 @@ class IVSwitchOvs(IVSwitch, tasks.Process): assert 'Port "%s"' % port_name not in output[0] return True - def validate_add_flow(self, result, switch_name, flow, cache='off'): + def validate_add_flow(self, dummy_result, switch_name, flow, dummy_cache='off'): """ Validate insertion of the flow into the switch """ + if 'idle_timeout' in flow: - del(flow['idle_timeout']) + del flow['idle_timeout'] # Note: it should be possible to call `ovs-ofctl dump-flows switch flow` # to verify flow insertion, but it doesn't accept the same flow syntax @@ -439,38 +443,38 @@ class IVSwitchOvs(IVSwitch, tasks.Process): return True return False - def validate_del_flow(self, result, switch_name, flow=None): + def validate_del_flow(self, dummy_result, switch_name, flow=None): """ Validate removal of the flow """ if not flow: # what else we can do? return True - return not self.validate_add_flow(result, switch_name, flow) + return not self.validate_add_flow(dummy_result, switch_name, flow) - def validate_dump_flows(self, result, switch_name): + def validate_dump_flows(self, dummy_result, dummy_switch_name): """ Validate call of flow dump """ return True - def validate_disable_rstp(self, result, switch_name): + def validate_disable_rstp(self, dummy_result, switch_name): """ Validate rstp disable """ bridge = self._bridges[switch_name] return 'rstp_enable : false' in ''.join(bridge.bridge_info()) - def validate_enable_rstp(self, result, switch_name): + def validate_enable_rstp(self, dummy_result, switch_name): """ Validate rstp enable """ bridge = self._bridges[switch_name] return 'rstp_enable : true' in ''.join(bridge.bridge_info()) - def validate_disable_stp(self, result, switch_name): + def validate_disable_stp(self, dummy_result, switch_name): """ Validate stp disable """ bridge = self._bridges[switch_name] return 'stp_enable : false' in ''.join(bridge.bridge_info()) - def validate_enable_stp(self, result, switch_name): + def validate_enable_stp(self, dummy_result, switch_name): """ Validate stp enable """ bridge = self._bridges[switch_name] diff --git a/vswitches/ovs_dpdk_vhost.py b/vswitches/ovs_dpdk_vhost.py index 40f4533b..3387fda7 100644 --- a/vswitches/ovs_dpdk_vhost.py +++ b/vswitches/ovs_dpdk_vhost.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import subprocess from src.ovs import OFBridge from src.dpdk import dpdk -from conf import settings +from conf import settings as S from vswitches.ovs import IVSwitchOvs class OvsDpdkVhost(IVSwitchOvs): @@ -43,7 +43,14 @@ class OvsDpdkVhost(IVSwitchOvs): # legacy DPDK configuration through --dpdk option of vswitchd if self.old_dpdk_config(): - vswitchd_args = ['--dpdk'] + settings.getValue('VSWITCHD_DPDK_ARGS') + # override socket-mem settings + tmp_dpdk_args = S.getValue('VSWITCHD_DPDK_ARGS') + for tmp_arg in tmp_dpdk_args: + if tmp_arg.startswith('--socket-mem'): + tmp_dpdk_args.remove(tmp_arg) + tmp_dpdk_args += ['--socket-mem ' + ','.join(S.getValue('DPDK_SOCKET_MEM'))] + vswitchd_args = ['--dpdk'] + tmp_dpdk_args + # add dpdk args to generic ovs-vswitchd settings if self._vswitchd_args: self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args else: @@ -52,8 +59,10 @@ class OvsDpdkVhost(IVSwitchOvs): def configure(self): """ Configure vswitchd DPDK options through ovsdb if needed """ - dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG') + dpdk_config = S.getValue('VSWITCHD_DPDK_CONFIG') if dpdk_config and not self.old_dpdk_config(): + # override socket-mem settings + dpdk_config['dpdk-socket-mem'] = ','.join(S.getValue('DPDK_SOCKET_MEM')) # enforce calls to ovs-vsctl with --no-wait tmp_br = OFBridge(timeout=-1) for option in dpdk_config: @@ -68,12 +77,12 @@ class OvsDpdkVhost(IVSwitchOvs): dpdk.init() super(OvsDpdkVhost, self).start() # old style OVS <= 2.5.0 multi-queue enable - if settings.getValue('OVS_OLD_STYLE_MQ') and \ - int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')): + if S.getValue('OVS_OLD_STYLE_MQ') and \ + int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES')): tmp_br = OFBridge(timeout=-1) tmp_br.set_db_attribute( 'Open_vSwitch', '.', 'other_config:' + - 'n-dpdk-rxqs', settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) + 'n-dpdk-rxqs', S.getValue('VSWITCH_DPDK_MULTI_QUEUES')) def stop(self): """See IVswitch for general description @@ -92,12 +101,12 @@ class OvsDpdkVhost(IVSwitchOvs): switch_params = switch_params + params super(OvsDpdkVhost, self).add_switch(switch_name, switch_params) - if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1: + if S.getValue('VSWITCH_AFFINITIZATION_ON') == 1: # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK # for CPU core affinitization self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.', 'other_config:pmd-cpu-mask', - settings.getValue('VSWITCH_PMD_CPU_MASK')) + S.getValue('VSWITCH_PMD_CPU_MASK')) def add_phy_port(self, switch_name): """See IVswitch for general description @@ -110,15 +119,15 @@ class OvsDpdkVhost(IVSwitchOvs): port_name = 'dpdk' + str(dpdk_count) # PCI info. Please note there must be no blank space, eg must be # like 'options:dpdk-devargs=0000:06:00.0' - _NICS = settings.getValue('NICS') - nic_pci = 'options:dpdk-devargs=' + _NICS[dpdk_count]['pci'] + _nics = S.getValue('NICS') + nic_pci = 'options:dpdk-devargs=' + _nics[dpdk_count]['pci'] params = ['--', 'set', 'Interface', port_name, 'type=dpdk', nic_pci] # multi-queue enable - if int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \ - not settings.getValue('OVS_OLD_STYLE_MQ'): + if int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \ + not S.getValue('OVS_OLD_STYLE_MQ'): params += ['options:n_rxq={}'.format( - settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))] + S.getValue('VSWITCH_DPDK_MULTI_QUEUES'))] of_port = bridge.add_port(port_name, params) return (port_name, of_port) @@ -144,9 +153,24 @@ class OvsDpdkVhost(IVSwitchOvs): :returns: True if legacy --dpdk option is supported, otherwise it returns False """ - ovs_vswitchd_bin = settings.getValue('TOOLS')['ovs-vswitchd'] + ovs_vswitchd_bin = S.getValue('TOOLS')['ovs-vswitchd'] try: subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True) return True except subprocess.CalledProcessError: return False + + def add_connection(self, switch_name, port1, port2, bidir=False): + """See IVswitch for general description + """ + raise NotImplementedError() + + def del_connection(self, switch_name, port1, port2, bidir=False): + """See IVswitch for general description + """ + raise NotImplementedError() + + def dump_connections(self, switch_name): + """See IVswitch for general description + """ + raise NotImplementedError() diff --git a/vswitches/ovs_vanilla.py b/vswitches/ovs_vanilla.py index 12a460af..75870ab7 100644 --- a/vswitches/ovs_vanilla.py +++ b/vswitches/ovs_vanilla.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2017 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,7 +19,6 @@ import logging from conf import settings from vswitches.ovs import IVSwitchOvs from src.ovs import DPCtl -from tools.module_manager import ModuleManager from tools import tasks class OvsVanilla(IVSwitchOvs): @@ -41,7 +40,6 @@ class OvsVanilla(IVSwitchOvs): self._logger = logging.getLogger(__name__) self._vswitchd_args += ["unix:%s" % self.get_db_sock_path()] self._vswitchd_args += settings.getValue('VSWITCHD_VANILLA_ARGS') - self._module_manager = ModuleManager() def stop(self): """See IVswitch for general description @@ -75,8 +73,7 @@ class OvsVanilla(IVSwitchOvs): self._logger.error("Can't add port! There are only " + len(self._ports) + " ports " + "defined in config!") - raise - + raise RuntimeError('Failed to add phy port') if not self._ports[self._current_id]: self._logger.error("Can't detect device name for NIC %s", self._current_id) raise ValueError("Invalid device name for %s" % self._current_id) @@ -129,4 +126,17 @@ class OvsVanilla(IVSwitchOvs): of_port = bridge.add_port(tap_name, []) return (tap_name, of_port) + def add_connection(self, switch_name, port1, port2, bidir=False): + """See IVswitch for general description + """ + raise NotImplementedError() + + def del_connection(self, switch_name, port1, port2, bidir=False): + """See IVswitch for general description + """ + raise NotImplementedError() + def dump_connections(self, switch_name): + """See IVswitch for general description + """ + raise NotImplementedError() diff --git a/vswitches/vpp_dpdk_vhost.py b/vswitches/vpp_dpdk_vhost.py new file mode 100644 index 00000000..d0d9e2ac --- /dev/null +++ b/vswitches/vpp_dpdk_vhost.py @@ -0,0 +1,403 @@ +# Copyright 2017 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. + +"""VSPERF VPP implementation using DPDK and vhostuser vports +""" + +import logging +import os +import copy +import re +import pexpect + +from src.dpdk import dpdk +from conf import settings as S +from vswitches.vswitch import IVSwitch +from tools import tasks + +# pylint: disable=too-many-public-methods +class VppDpdkVhost(IVSwitch, tasks.Process): + """ VPP with DPDK support + """ + _proc_name = 'vpp' + _bridge_idx_counter = 100 + + def __init__(self): + """See IVswitch for general description + """ + self._logfile = os.path.join(S.getValue('LOG_DIR'), + S.getValue('LOG_FILE_VPP')) + self._logger = logging.getLogger(__name__) + self._expect = r'vpp#' + self._timeout = 30 + self._vswitch_args = [] + self._cmd = [] + self._cmd_template = ['sudo', '-E', S.getValue('TOOLS')['vpp']] + self._stamp = None + self._logger = logging.getLogger(__name__) + self._phy_ports = [] + self._virt_ports = [] + self._switches = {} + + # configure DPDK NICs + tmp_args = copy.deepcopy(S.getValue('VSWITCH_VPP_ARGS')) + if 'dpdk' not in tmp_args: + tmp_args['dpdk'] = [] + + # override socket-mem settings + for tmp_arg in tmp_args['dpdk']: + if tmp_arg.startswith('socket-mem'): + tmp_args['dpdk'].remove(tmp_arg) + tmp_args['dpdk'].append('socket-mem ' + + ','.join(S.getValue('DPDK_SOCKET_MEM'))) + + for nic in S.getValue('NICS'): + tmp_args['dpdk'].append("dev {}".format(nic['pci'])) + self._vswitch_args = self._process_vpp_args(tmp_args) + + def _get_nic_info(self, key='Name'): + """Read NIC info from VPP and return NIC details in a dictionary + indexed by given ``key`` + + :param key: Name of the key to be used for indexing result dictionary + + :returns: Dictionary with NIC infos including their PCI addresses + """ + result = {} + output = self.run_vppctl(['show', 'hardware', 'brief']) + # parse output and store basic info about NICS + ifaces = output[0].split('\n') + keys = ifaces[0].split() + keys.append('Pci') + keyidx = keys.index(key) + for iface in ifaces[1:]: + tmpif = iface.split() + # get PCI address of given interface + output = self.run_vppctl(['show', 'hardware', tmpif[1], 'detail']) + match = re.search(r'pci address:\s*([\d:\.]+)', output[0]) + if match: + # normalize PCI address, e.g. 0000:05:10.01 => 0000:05:10.1 + tmp_pci = match.group(1).split('.') + tmp_pci[1] = str(int(tmp_pci[1])) + tmpif.append('.'.join(tmp_pci)) + else: + tmpif.append(None) + # store only NICs with reasonable index + if tmpif[keyidx] is not None: + result[tmpif[keyidx]] = dict(zip(keys, tmpif)) + + return result + + def _process_vpp_args(self, args): + """Produce VPP CLI args from input dictionary ``args`` + """ + cli_args = [] + for cfg_key in args: + cli_args.append(cfg_key) + cli_args.append("{{ {} }}".format(' '.join(args[cfg_key]))) + + self._logger.debug("VPP CLI args: %s", cli_args) + return cli_args + + + def start(self): + """Activates DPDK kernel modules and starts VPP + + :raises: pexpect.EOF, pexpect.TIMEOUT + """ + dpdk.init() + self._logger.info("Starting VPP...") + + self._cmd = self._cmd_template + self._vswitch_args + + try: + tasks.Process.start(self) + self.relinquish() + except (pexpect.EOF, pexpect.TIMEOUT) as exc: + logging.error("Exception during VPP start.") + raise exc + + self._logger.info("VPP...Started.") + + def stop(self): + """See IVswitch for general description + + Kills VPP and removes DPDK kernel modules. + """ + self._logger.info("Terminating VPP...") + self.kill() + self._logger.info("VPP...Terminated.") + dpdk.cleanup() + + def kill(self, signal='-15', sleep=10): + """See IVswitch for general description + + Kills ``vpp`` + """ + # try to get VPP pid + output = self.run_vppctl(['show', 'version', 'verbose']) + match = re.search(r'Current PID:\s*([0-9]+)', output[0]) + if match: + vpp_pid = match.group(1) + tasks.terminate_task(vpp_pid, logger=self._logger) + + # in case, that pid was not detected or sudo envelope + # has not been terminated yet + tasks.Process.kill(self, signal, sleep) + + def add_switch(self, switch_name, dummy_params=None): + """See IVswitch for general description + """ + if switch_name in self._switches: + self._logger.warning("switch %s already exists...", switch_name) + else: + self._switches[switch_name] = self._bridge_idx_counter + self._bridge_idx_counter += 1 + + def del_switch(self, switch_name): + """See IVswitch for general description + """ + if switch_name in self._switches: + del self._switches[switch_name] + + def add_phy_port(self, dummy_switch_name): + """See IVswitch for general description + :raises: RuntimeError + """ + # get list of physical interfaces with PCI addresses + vpp_nics = self._get_nic_info(key='Pci') + # check if there are any NICs left + if len(self._phy_ports) >= len(S.getValue('NICS')): + raise RuntimeError('All available NICs are already configured!') + + nic = S.getValue('NICS')[len(self._phy_ports)] + if not nic['pci'] in vpp_nics: + raise RuntimeError('VPP cannot access nic with PCI address: {}'.format(nic['pci'])) + nic_name = vpp_nics[nic['pci']]['Name'] + self._phy_ports.append(nic_name) + self.run_vppctl(['set', 'int', 'state', nic_name, 'up']) + return (nic_name, vpp_nics[nic['pci']]['Idx']) + + def add_vport(self, dummy_switch_name): + """See IVswitch for general description + """ + socket_name = S.getValue('TOOLS')['ovs_var_tmp'] + 'dpdkvhostuser' + str(len(self._virt_ports)) + output = self.run_vppctl(['create', 'vhost-user', 'socket', socket_name, 'server'] + + S.getValue('VSWITCH_VPP_VHOSTUSER_ARGS')) + nic_name = output[0] + self._virt_ports.append(nic_name) + self.run_vppctl(['set', 'int', 'state', nic_name, 'up']) + return (nic_name, None) + + def del_port(self, switch_name, port_name): + """See IVswitch for general description + """ + if port_name in self._phy_ports: + self.run_vppctl(['set', 'int', 'state', port_name, 'down']) + self._phy_ports.remove(port_name) + elif port_name in self._virt_ports: + self.run_vppctl(['set', 'int', 'state', port_name, 'down']) + self.run_vppctl(['delete', 'vhost-user', port_name]) + self._virt_ports.remove(port_name) + else: + self._logger.warning("Port %s is not configured.", port_name) + + def add_l2patch(self, port1, port2, bidir=False): + """Create l2patch connection between given ports + """ + self.run_vppctl(['test', 'l2patch', 'rx', port1, 'tx', port2]) + if bidir: + self.run_vppctl(['test', 'l2patch', 'rx', port2, 'tx', port1]) + + def add_xconnect(self, port1, port2, bidir=False): + """Create l2patch connection between given ports + """ + self.run_vppctl(['set', 'interface', 'l2', 'xconnect', port1, port2]) + if bidir: + self.run_vppctl(['set', 'interface', 'l2', 'xconnect', port2, port1]) + + def add_bridge(self, switch_name, port1, port2, dummy_bidir=False): + """Add given ports to bridge ``switch_name`` + """ + self.run_vppctl(['set', 'interface', 'l2', 'bridge', port1, + str(self._switches[switch_name])]) + self.run_vppctl(['set', 'interface', 'l2', 'bridge', port2, + str(self._switches[switch_name])]) + + def add_connection(self, switch_name, port1, port2, bidir=False): + """See IVswitch for general description + + :raises: RuntimeError + """ + mode = S.getValue('VSWITCH_VPP_L2_CONNECT_MODE') + if mode == 'l2patch': + self.add_l2patch(port1, port2, bidir) + elif mode == 'xconnect': + self.add_xconnect(port1, port2, bidir) + elif mode == 'bridge': + self.add_bridge(switch_name, port1, port2) + else: + raise RuntimeError('VPP: Unsupported l2 connection mode detected %s', mode) + + def del_l2patch(self, port1, port2, bidir=False): + """Remove l2patch connection between given ports + + :param port1: port to be used in connection + :param port2: port to be used in connection + :param bidir: switch between uni and bidirectional traffic + """ + self.run_vppctl(['test', 'l2patch', 'rx', port1, 'tx', port2, 'del']) + if bidir: + self.run_vppctl(['test', 'l2patch', 'rx', port2, 'tx', port1, 'del']) + + def del_xconnect(self, dummy_port1, dummy_port2, dummy_bidir=False): + """Remove xconnect connection between given ports + """ + self._logger.warning('VPP: Removal of l2 xconnect is not implemented.') + + def del_bridge(self, dummy_switch_name, dummy_port1, dummy_port2): + """Remove given ports from the bridge + """ + self._logger.warning('VPP: Removal of interfaces from bridge is not implemented.') + + def del_connection(self, switch_name, port1, port2, bidir=False): + """See IVswitch for general description + + :raises: RuntimeError + """ + mode = S.getValue('VSWITCH_VPP_L2_CONNECT_MODE') + if mode == 'l2patch': + self.del_l2patch(port1, port2, bidir) + elif mode == 'xconnect': + self.del_xconnect(port1, port2, bidir) + elif mode == 'bridge': + self.del_bridge(switch_name, port1, port2) + else: + raise RuntimeError('VPP: Unsupported l2 connection mode detected %s', mode) + + def dump_l2patch(self): + """Dump l2patch connections + """ + self.run_vppctl(['show', 'l2patch']) + + def dump_xconnect(self): + """Dump l2 xconnect connections + """ + self._logger.warning("VPP: Dump of l2 xconnections is not supported.") + + def dump_bridge(self, switch_name): + """Show bridge details + + :param switch_name: switch on which to operate + """ + self.run_vppctl(['show', 'bridge-domain', str(self._switches[switch_name]), 'int']) + + def dump_connections(self, switch_name): + """See IVswitch for general description + + :raises: RuntimeError + """ + mode = S.getValue('VSWITCH_VPP_L2_CONNECT_MODE') + if mode == 'l2patch': + self.dump_l2patch() + elif mode == 'xconnect': + self.dump_xconnect() + elif mode == 'bridge': + self.dump_bridge(switch_name) + else: + raise RuntimeError('VPP: Unsupported l2 connection mode detected %s', mode) + + def run_vppctl(self, args, check_error=False): + """Run ``vppctl`` with supplied arguments. + + :param args: Arguments to pass to ``vppctl`` + :param check_error: Throw exception on error + + :return: None + """ + cmd = ['sudo', S.getValue('TOOLS')['vppctl']] + args + return tasks.run_task(cmd, self._logger, 'Running vppctl...', check_error) + + # + # Validate methods + # + def validate_add_switch(self, dummy_result, switch_name, dummy_params=None): + """Validate - Create a new logical switch with no ports + """ + return switch_name in self._switches + + def validate_del_switch(self, dummy_result, switch_name): + """Validate removal of switch + """ + return not self.validate_add_switch(dummy_result, switch_name) + + def validate_add_phy_port(self, result, dummy_switch_name): + """ Validate that physical port was added to bridge. + """ + return result[0] in self._phy_ports + + def validate_add_vport(self, result, dummy_switch_name): + """ Validate that virtual port was added to bridge. + """ + return result[0] in self._virt_ports + + def validate_del_port(self, dummy_result, dummy_switch_name, port_name): + """ Validate that port_name was removed from bridge. + """ + return not (port_name in self._phy_ports or port_name in self._virt_ports) + + # pylint: disable=no-self-use + def validate_run_vppctl(self, result, dummy_args, dummy_check_error=False): + """validate execution of ``vppctl`` with supplied arguments. + """ + # there shouldn't be any stderr + return not result[1] + + # + # Non implemented methods + # + def add_flow(self, switch_name, flow, cache='off'): + """See IVswitch for general description + """ + raise NotImplementedError() + + def del_flow(self, switch_name, flow=None): + """See IVswitch for general description + """ + raise NotImplementedError() + + def dump_flows(self, switch_name): + """See IVswitch for general description + """ + raise NotImplementedError() + + def add_route(self, switch_name, network, destination): + """See IVswitch for general description + """ + raise NotImplementedError() + + def set_tunnel_arp(self, ip_addr, mac_addr, switch_name): + """See IVswitch for general description + """ + raise NotImplementedError() + + def add_tunnel_port(self, switch_name, remote_ip, tunnel_type='vxlan', params=None): + """See IVswitch for general description + """ + raise NotImplementedError() + + def get_ports(self, switch_name): + """See IVswitch for general description + """ + raise NotImplementedError() diff --git a/vswitches/vswitch.py b/vswitches/vswitch.py index 73e0a0c3..893bd1ff 100644 --- a/vswitches/vswitch.py +++ b/vswitches/vswitch.py @@ -130,6 +130,39 @@ class IVSwitch(object): """ raise NotImplementedError() + def add_connection(self, switch_name, port1, port2, bidir=False): + """Creates connection between given ports. + + :param switch_name: switch on which to operate + :param port1: port to be used in connection + :param port2: port to be used in connection + :param bidir: switch between uni and bidirectional traffic + + :raises: RuntimeError + """ + raise NotImplementedError() + + def del_connection(self, switch_name, port1, port2, bidir=False): + """Remove connection between two interfaces. + + :param switch_name: switch on which to operate + :param port1: port to be used in connection + :param port2: port to be used in connection + :param bidir: switch between uni and bidirectional traffic + + :raises: RuntimeError + """ + raise NotImplementedError() + + def dump_connections(self, switch_name): + """Dump connections between interfaces. + + :param switch_name: switch on which to operate + + :raises: RuntimeError + """ + raise NotImplementedError() + def dump_flows(self, switch_name): """Dump flows from the logical switch |