diff options
author | Luc Provoost <luc.provoost@intel.com> | 2019-04-12 11:20:58 +0200 |
---|---|---|
committer | Luc Provoost <luc.provoost@intel.com> | 2019-04-12 11:20:58 +0200 |
commit | d4216dd28019256fd6363ed4269d540ef64ec23c (patch) | |
tree | 60f2fbae8433616b972c804e6dc9525e0757bd07 | |
parent | af95b812c39e7fa039b7041b6cb8aba0c5e88c02 (diff) |
Improved image building & new PROX
Bug fixes for the script for building an image via the packer tool. This
also installs a newer version of PROX with some bug fixes in PROX. The
*.test files have been simplified. Also introduced a new file
MachineMap.cfg to map test machines on actual VMs.
Change-Id: I69445327ef0a907bc8c1566aaa60c733418c541e
Signed-off-by: Luc Provoost <luc.provoost@intel.com>
25 files changed, 764 insertions, 551 deletions
diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/deploycentos1.sh b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/MachineMap.cfg index c65a4833..b6e199d7 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/deploycentos1.sh +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/MachineMap.cfg @@ -1,5 +1,3 @@ -#!/bin/bash - ## ## Copyright (c) 2010-2018 Intel Corporation ## @@ -15,11 +13,18 @@ ## See the License for the specific language governing permissions and ## limitations under the License. ## -sudo yum install deltarpm -y -sudo yum update -y -sudo yum-config-manager --add-repo http://www.nasm.us/nasm.repo -sudo yum install git wget gcc unzip libpcap-devel ncurses-devel libedit-devel lua-devel kernel-devel iperf3 pciutils numactl-devel vim tuna openssl-devel nasm -y -# Enabling root ssh access -sudo sed -i '/disable_root: 1/c\disable_root: 0' /etc/cloud/cloud.cfg -# Reboot, before continuing with deploycentos2.sh -sudo reboot +## This file contains the mapping for each test machine. The test machine will +## be deployed on a machine defined in the *.env file, as defined by the +## machine_index + +[DEFAULT] +machine_index=0 + +[TestM1] +machine_index=1 + +[TestM2] +machine_index=2 + +[TestM3] +machine_index=3 diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/README b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/README index 0dea6565..43243a6c 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/README +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/README @@ -21,19 +21,18 @@ rapid is a set of files offering an easy way to do a sanity check of the dataplane performance of an OpenStack environment. Copy the files in a directory on a machine that can run the OpenStack CLI -commands and that can reach the OpenStack public network. +commands and that can reach the OpenStack networks to connect to the VMs. You will need an image that has the PROX tool installed. -The best way to do this is to use the packer tool to build an image for a target of your choice. -You can also build this image manually by executing all the commands described in the deploycentos1.sh -and deploycentos2.sh file. -The default name of the qcow2 file should is rapidVM.qcow2 +A good way to do this is to use the packer tool to build an image for a target of your choice. +You can also build this image manually by executing all the commands described in the deploycentos.sh. +The default name of the qcow2 file is rapidVM.qcow2 When using the packer tool, the first step is to upload an -existing CentOs cloud image from the internet into OpenStack. +existing CentOS cloud image from the internet into OpenStack. Check out: https://cloud.centos.org/centos/7/images/ You should now source the proper .rc file so Packer can connect to your OpenStack. -There are 3 files: centos.json, deploycentos1.sh and deploycentos2.sh, allowing you to create +There are 2 files: centos.json and deploycentos.sh, allowing you to create an image automatically. Run # packer build centos.json Edit centos.json to reflect the settings of your environment: The following fields need to @@ -47,7 +46,7 @@ be the ID's of your system: - "security_groups": ID of the security group being used Note that this procedure is not only installing the necessary tools to run PROX, -but also does some system optimizations (tuned). +but also does some system optimizations (tuned). Check deploycentos.sh for more details. Now you can run the createrapid.py file. Use help for more info on the usage: # ./createrapid.py --help @@ -58,12 +57,11 @@ It will create a <STACK>.env file containing all info that will be used by runra to actually run the tests. Logging can be found in the CREATE<STACK>.log file You can use floating IP addresses by specifying the floating IP network --floating_network NETWORK -or directly connect throught the INTERNAL_NETWORK by using the following parameter: +or directly connect through the INTERNAL_NETWORK by using the following parameter: --floating_network NO /etc/resolv.conf will contain DNS info from the "best" interface. Since we are deploying VMs with multiple interface on different networks, this info might be -taken from the "wrong" network (e.g. the dataplane network). It is good to provide -also a working DNS on that network. +taken from the "wrong" network (e.g. the dataplane network). Now you can run the runrapid.py file. Use help for more info on the usage: # ./runrapid.py --help @@ -71,6 +69,7 @@ The script will connect to all machines that have been instantiated and it will PROX in all machines. This will be done through the admin IP assigned to the machines. Once that is done it will connect to the PROX tcp socket and start sending commands to run the actual test. +Make sure the security groups allow for tcp access (ssh & prox port). It will print test results on the screen while running. The actual test that is running is described in <TEST>.test. @@ -114,35 +113,37 @@ achieved using createrapid.py. Fields needed for runrapid are: admin_ip = none [M1] -admin_ip = 192.168.4.130 -dp_ip = 10.10.10.6 -dp_mac = fa:16:3e:3c:1e:12 +name = rapid-VM1 +admin_ip = 10.25.1.116 +dp_ip = 10.10.10.7 +dp_mac = fa:16:3e:59:b8:28 [M2] -admin_ip = 192.168.4.140 -dp_ip = 10.10.10.9 -dp_mac = fa:16:3e:2a:00:5d +name = rapid-VM2 +admin_ip = 10.25.1.126 +dp_ip = 10.10.10.11 +dp_mac = fa:16:3e:c9:54:c7 [M3] -admin_ip = 192.168.4.138 -dp_ip = 10.10.10.11 -dp_mac = fa:16:3e:ae:fa:86 +name = rapid-VM3 +admin_ip = 10.25.1.108 +dp_ip = 10.10.10.15 +dp_mac = fa:16:3e:72:90:3e [OpenStack] stack = rapid -yaml = 3VMrapid.yaml +vms = rapidVMs key = prox -flavor = prox_flavor image = rapidVM image_file = rapidVM.qcow2 dataplane_network = dataplane-network subnet = dpdk-subnet subnet_cidr = 10.10.10.0/24 internal_network = admin_internal_net -floating_network = admin_floating_net +floating_network = floating-ip-net [rapid] loglevel = DEBUG -version = 17.10.25 -total_number_of_vms = 3 +version = 19.4.15 +total_number_of_machines = 3 diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/basicrapid.test b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/basicrapid.test index 8d73711b..b2f8f230 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/basicrapid.test +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/basicrapid.test @@ -16,41 +16,45 @@ [DEFAULT] name = BasicSwapTesting -number_of_tests = 3 +number_of_tests = 4 total_number_of_test_machines = 2 -init_code=init_test() -dest_vm = not_used -gw_vm = not_used -script_control = false -group1cores = not_used -group2cores = not_used -group3cores = not_used -drop_rate_treshold = 0.1 -lat_avg_treshold = 200 -lat_max_treshold = 1000 -accuracy = 0.1 -startspeed = 10 - +prox_socket = true +prox_launch_exit = true [TestM1] name = Generator -machine_index = 1 config_file = gen.cfg dest_vm = 2 -script_control = true -group1cores = [1] -group2cores = [3] -group3cores = [1,3] +gencores = [1] +latcores = [3] +startspeed = 10 [TestM2] name = Swap -machine_index = 2 config_file = swap.cfg -group1cores = [1] +swapcores = [1] + +[BinarySearchParams] +drop_rate_threshold = 0.1 +lat_avg_threshold = 500 +lat_max_threshold = 1000 +accuracy = 0.1 [test1] -cmd=run_speedtest(socks[0],socks[1]) +test=inittest + [test2] -cmd=run_sizetest(socks[0],socks[1]) +test=speedtest +packetsize=64 + [test3] -cmd=run_flowtest(socks[0],socks[1]) +test=sizetest +flow=1 +packetsizes=[64,256,1024] + +[test4] +test=flowtest +packetsize=64 +# the number of flows in the list need to be powers of 2, max 2^20 +# Select from following numbers: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65535, 131072, 262144, 524280, 1048576 +flows=[1,512,1024] diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/centos.json b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/centos.json index 1676f2f7..237a6483 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/centos.json +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/centos.json @@ -5,13 +5,13 @@ { "type": "openstack", "ssh_username": "centos", -"image_name": "PROXffc6be26-DPDK1808VM", -"source_image": "aa0f8333-d8e1-42db-8210-6b39d9ee7267", -"flavor": "7aaec028-eccc-4612-8f9b-29a1e039943a", -"networks": "97bbe96f-ee1b-4789-ace8-e922f76bea3f", +"image_name": "rapidVM", +"source_image": "06101dd4-f162-49c0-a072-2fe32ac446a9", +"flavor": "3ea20ea9-855c-4a6e-b454-63ad6e8e0db9", +"networks": "451a030a-eb1e-4c74-85b8-782ef8a6ad38", "use_floating_ip": true, -"floating_ip_pool": "1f564356-8c23-41e2-8292-7696ffd98adf", -"security_groups": "8fd498fc-5bd8-4be6-94e4-a2cc3b02d151" +"floating_ip_pool": "d629619f-8f96-4f32-9b90-1b62e5ea3809", +"security_groups": "460b7929-c6de-4b1c-ae83-901c2042a894" } ], "provisioners": [ @@ -27,13 +27,7 @@ }, { "type": "shell", - "script": "deploycentos1.sh", - "expect_disconnect": true - }, - { - "type": "shell", - "script": "deploycentos2.sh", - "pause_before": "20s" + "script": "deploycentos.sh" } ] } diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/createrapid.py b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/createrapid.py index 06e2f232..a1c1de60 100755 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/createrapid.py +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/createrapid.py @@ -31,7 +31,7 @@ from logging import handlers from prox_ctrl import prox_ctrl import ConfigParser -version="19.1.10" +version="19.4.15" stack = "rapid" #Default string for stack. This is not an OpenStack Heat stack, just a group of VMs vms = "rapidVMs" #Default string for vms file key = "prox" # default name for kay @@ -56,7 +56,7 @@ def usage(): print(" [--subnet DP_SUBNET]") print(" [--subnet_cidr SUBNET_CIDR]") print(" [--internal_network ADMIN_NETWORK]") - print(" [--floating_network ADMIN_NETWORK]") + print(" [--floating_network FLOATING_NETWORK]") print(" [--log DEBUG|INFO|WARNING|ERROR|CRITICAL]") print(" [-h] [--help]") print("") @@ -363,21 +363,23 @@ for vm in range(1, int(total_number_of_VMs)+1): if floating_network <> 'NO': for vm in range(0, int(total_number_of_VMs)): if ServerToBeCreated[vm] =="yes": - log.info('Creating floating IP ...') - cmd = 'openstack floating ip create ' + floating_network - log.debug(cmd) - cmd = cmd + ' |grep "floating_ip_address " | tr -s " " | cut -d"|" -f 3' - vmAdminIP = subprocess.check_output(cmd , shell=True).strip() - log.info('Associating floating IP ...') - cmd = 'openstack server add floating ip %s %s'%(ServerName[vm],vmAdminIP) - log.debug(cmd) - output = subprocess.check_output(cmd , shell=True).strip() + log.info('Creating & Associating floating IP for ('+ServerName[vm]+')...') + cmd = 'openstack server show %s -c addresses -f value |grep -Eo "%s=[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | cut -d"=" -f2'%(ServerName[vm],internal_network) + log.debug(cmd) + vmportIP = subprocess.check_output(cmd , shell=True).strip() + cmd = 'openstack port list -c ID -c "Fixed IP Addresses" | grep %s' %(vmportIP) + cmd = cmd + ' | cut -d" " -f 2 ' + log.debug(cmd) + vmportID = subprocess.check_output(cmd , shell=True).strip() + cmd = 'openstack floating ip create --port %s %s'%(vmportID,floating_network) + log.debug(cmd) + output = subprocess.check_output(cmd , shell=True).strip() for vm in range(1, int(total_number_of_VMs)+1): cmd = 'openstack server show %s'%(ServerName[vm-1]) log.debug(cmd) output = subprocess.check_output(cmd , shell=True).strip() - searchString = '.*%s.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)' %(dataplane_network) + searchString = '.*%s=([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)' %(dataplane_network) matchObj = re.search(searchString, output, re.DOTALL) vmDPIP = matchObj.group(1) searchString = '.*%s=([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+),*\s*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)*' %(internal_network) diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/deploycentos.sh b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/deploycentos.sh new file mode 100644 index 00000000..848520ce --- /dev/null +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/deploycentos.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +## +## Copyright (c) 2010-2019 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. +## + +BUILD_DIR="/opt/openstackrapid" +COPY_DIR="/home/centos" # Directory where the packer tool has copied some files +DPDK_VERSION="18.08" +PROX_COMMIT="af95b812" +export RTE_SDK="${BUILD_DIR}/dpdk-${DPDK_VERSION}" +export RTE_TARGET="x86_64-native-linuxapp-gcc" + +function os_pkgs_install() +{ + # NASM repository for AESNI MB library + sudo yum-config-manager --add-repo http://www.nasm.us/nasm.repo + + sudo yum install -y deltarpm + sudo yum update -y + sudo yum install -y git wget gcc unzip libpcap-devel ncurses-devel \ + libedit-devel lua-devel kernel-devel iperf3 pciutils \ + numactl-devel vim tuna openssl-devel nasm +} + +function os_cfg() +{ + # Enabling root ssh access + sudo sed -i '/disable_root: 1/c\disable_root: 0' /etc/cloud/cloud.cfg + + # Mounting huge pages to be used by DPDK, mounting already done by CentOS + # sudo mkdir -p /mnt/huge + # sudo umount `awk '/hugetlbfs/ { print $2 }' /proc/mounts` >/dev/null 2>&1 + # sudo mount -t hugetlbfs nodev /mnt/huge/ + sudo sh -c '(echo "vm.nr_hugepages = 1024") > /etc/sysctl.conf' + + # Enabling tuned with the realtime-virtual-guest profile + pushd ${BUILD_DIR} > /dev/null 2>&1 + wget http://linuxsoft.cern.ch/cern/centos/7/rt/x86_64/Packages/tuned-profiles-realtime-2.8.0-5.el7_4.2.noarch.rpm + wget http://linuxsoft.cern.ch/cern/centos/7/rt/x86_64/Packages/tuned-profiles-nfv-guest-2.8.0-5.el7_4.2.noarch.rpm + # Install with --nodeps. The latest CentOS cloud images come with a tuned version higher than 2.8. These 2 packages however + # do not depend on v2.8 and also work with tuned 2.9. Need to be careful in the future + sudo rpm -ivh ${BUILD_DIR}/tuned-profiles-realtime-2.8.0-5.el7_4.2.noarch.rpm --nodeps + sudo rpm -ivh ${BUILD_DIR}/tuned-profiles-nfv-guest-2.8.0-5.el7_4.2.noarch.rpm --nodeps + # Although we do no know how many cores the VM will have when begin deployed for real testing, we already put a number for the + # isolated CPUs so we can start the realtime-virtual-guest profile. If we don't, that command will fail. + # When the VM will be instantiated, the check_kernel_params service will check for the real number of cores available to this VM + # and update the realtime-virtual-guest-variables.conf accordingly. + echo "isolated_cores=1" | sudo tee -a /etc/tuned/realtime-virtual-guest-variables.conf + sudo tuned-adm profile realtime-virtual-guest + + # Install the check_tuned_params service to make sure that the grub cmd line has the right cpus in isolcpu. The actual number of cpu's + # assigned to this VM depends on the flavor used. We don't know at this time what that will be. + sudo chmod +x ${COPY_DIR}/check_prox_system_setup.sh + sudo cp -r ${COPY_DIR}/check_prox_system_setup.sh /usr/local/libexec/ + sudo cp -r ${COPY_DIR}/check-prox-system-setup.service /etc/systemd/system/ + sudo systemctl daemon-reload + sudo systemctl enable check-prox-system-setup.service + + popd > /dev/null 2>&1 +} + +function mblib_install() +{ + export AESNI_MULTI_BUFFER_LIB_PATH="${BUILD_DIR}/intel-ipsec-mb-0.50" + + # Downloading the Multi-buffer library. Note that the version to download is linked to the DPDK version being used + pushd ${BUILD_DIR} > /dev/null 2>&1 + wget https://github.com/01org/intel-ipsec-mb/archive/v0.50.zip + unzip v0.50.zip + pushd ${AESNI_MULTI_BUFFER_LIB_PATH} + make -j`getconf _NPROCESSORS_ONLN` + sudo make install + popd > /dev/null 2>&1 + popd > /dev/null 2>&1 +} + +function dpdk_install() +{ + # Build DPDK for the latest kernel installed + LATEST_KERNEL_INSTALLED=`ls -v1 /lib/modules/ | tail -1` + export RTE_KERNELDIR="/lib/modules/${LATEST_KERNEL_INSTALLED}/build" + + # Get and compile DPDK + pushd ${BUILD_DIR} > /dev/null 2>&1 + wget http://fast.dpdk.org/rel/dpdk-${DPDK_VERSION}.tar.xz + tar -xf ./dpdk-${DPDK_VERSION}.tar.xz + popd > /dev/null 2>&1 + + # Runtime scripts are assuming /root as the directory for PROX + sudo ln -s ${RTE_SDK} /root/dpdk + + pushd ${RTE_SDK} > /dev/null 2>&1 + make config T=${RTE_TARGET} + # The next sed lines make sure that we can compile DPDK 17.11 with a relatively new OS. Using a newer DPDK (18.5) should also resolve this issue + #sudo sed -i '/CONFIG_RTE_LIBRTE_KNI=y/c\CONFIG_RTE_LIBRTE_KNI=n' ${RTE_SDK}/build/.config + #sudo sed -i '/CONFIG_RTE_LIBRTE_PMD_KNI=y/c\CONFIG_RTE_LIBRTE_PMD_KNI=n' ${RTE_SDK}/build/.config + #sudo sed -i '/CONFIG_RTE_KNI_KMOD=y/c\CONFIG_RTE_KNI_KMOD=n' ${RTE_SDK}/build/.config + #sudo sed -i '/CONFIG_RTE_KNI_PREEMPT_DEFAULT=y/c\CONFIG_RTE_KNI_PREEMPT_DEFAULT=n' ${RTE_SDK}/build/.config + # Compile with MB library + sed -i '/CONFIG_RTE_LIBRTE_PMD_AESNI_MB=n/c\CONFIG_RTE_LIBRTE_PMD_AESNI_MB=y' ${RTE_SDK}/build/.config + make -j`getconf _NPROCESSORS_ONLN` + ln -s ${RTE_SDK}/build ${RTE_SDK}/${RTE_TARGET} + popd > /dev/null 2>&1 +} + +function prox_install() +{ + # Clone and compile PROX + pushd ${BUILD_DIR} > /dev/null 2>&1 + git clone https://git.opnfv.org/samplevnf + pushd ${BUILD_DIR}/samplevnf/VNFs/DPPD-PROX +# git checkout ffc6be26 + git checkout ${PROX_COMMIT} + make -j`getconf _NPROCESSORS_ONLN` + sudo ln -s ${BUILD_DIR}/samplevnf/VNFs/DPPD-PROX /root/prox + popd > /dev/null 2>&1 + popd > /dev/null 2>&1 +} + +[ ! -d ${BUILD_DIR} ] && sudo mkdir -p ${BUILD_DIR} +sudo chmod 0777 ${BUILD_DIR} + +os_pkgs_install +os_cfg +mblib_install +dpdk_install +prox_install diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/deploycentos2.sh b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/deploycentos2.sh deleted file mode 100644 index 9a3157f6..00000000 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/deploycentos2.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/bash - -## -## Copyright (c) 2010-2018 Intel Corporation -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. -## -# The following line is commented since this was a workaround for a problem with the content of /etc/resolv.conf. -# That file could contain DNS information coming from the dataplane which might be wrong. A solution is to confire the correct DNS for the dataplne -# in OpenStack. DNS might be slowing down ssh access. We don't need that for our dataplane benchmarking purposes -# sudo sed -i '/#UseDNS yes/c\UseDNS no' /etc/ssh/sshd_config -sudo sh -c '(echo "export RTE_TARGET=\"build\"";echo "export RTE_SDK=\"/root/dpdk\"";echo "export AESNI_MULTI_BUFFER_LIB_PATH=\"/home/centos/intel-ipsec-mb-0.50\"";) >> /root/.bashrc' -export RTE_TARGET=build -export RTE_SDK=/home/centos/dpdk -export AESNI_MULTI_BUFFER_LIB_PATH=/home/centos/intel-ipsec-mb-0.50 -# Mounting huge pages to be used by DPDK -sudo mkdir -p /mnt/huge -sudo umount `awk '/hugetlbfs/ { print $2 }' /proc/mounts` >/dev/null 2>&1 -sudo mount -t hugetlbfs nodev /mnt/huge/ -sudo sh -c '(echo "vm.nr_hugepages = 1024") > /etc/sysctl.conf' - -# Downloading the Multi-buffer library. Note that the version to download is linked to the DPDK version being used -cd /home/centos -wget https://github.com/01org/intel-ipsec-mb/archive/v0.50.zip -unzip v0.50.zip -cd $AESNI_MULTI_BUFFER_LIB_PATH -make -sudo make install -# Clone and compile DPDK -cd /home/centos/ -git clone http://dpdk.org/git/dpdk -# Runtime scripts are assuming /root as the directory for PROX -sudo ln -s /home/centos/dpdk /root/dpdk -cd $RTE_SDK -git checkout v18.08 -make config T=x86_64-native-linuxapp-gcc -# The next sed lines make sure that we can compile DPDK 17.11 with a relatively new OS. Using a newer DPDK (18.5) should also resolve this issue -#sudo sed -i '/CONFIG_RTE_LIBRTE_KNI=y/c\CONFIG_RTE_LIBRTE_KNI=n' /home/centos/dpdk/build/.config -#sudo sed -i '/CONFIG_RTE_LIBRTE_PMD_KNI=y/c\CONFIG_RTE_LIBRTE_PMD_KNI=n' /home/centos/dpdk/build/.config -#sudo sed -i '/CONFIG_RTE_KNI_KMOD=y/c\CONFIG_RTE_KNI_KMOD=n' /home/centos/dpdk/build/.config -#sudo sed -i '/CONFIG_RTE_KNI_PREEMPT_DEFAULT=y/c\CONFIG_RTE_KNI_PREEMPT_DEFAULT=n' /home/centos/dpdk/build/.config -# Compile with MB library -sed -i '/CONFIG_RTE_LIBRTE_PMD_AESNI_MB=n/c\CONFIG_RTE_LIBRTE_PMD_AESNI_MB=y' /home/centos/dpdk/build/.config -make - -# Clone and compile PROX -cd /home/centos -git clone https://git.opnfv.org/samplevnf -cd /home/centos/samplevnf/VNFs/DPPD-PROX -git checkout ffc6be26 -make -sudo ln -s /home/centos/samplevnf/VNFs/DPPD-PROX /root/prox - -# Enabling tuned with the realtime-virtual-guest profile -cd /home/centos/ -wget http://linuxsoft.cern.ch/cern/centos/7/rt/x86_64/Packages/tuned-profiles-realtime-2.8.0-5.el7_4.2.noarch.rpm -wget http://linuxsoft.cern.ch/cern/centos/7/rt/x86_64/Packages/tuned-profiles-nfv-guest-2.8.0-5.el7_4.2.noarch.rpm -# Install with --nodeps. The latest CentOS cloud images come with a tuned version higher than 2.8. These 2 packages however -# do not depend on v2.8 and also work with tuned 2.9. Need to be careful in the future -sudo rpm -ivh /home/centos/tuned-profiles-realtime-2.8.0-5.el7_4.2.noarch.rpm --nodeps -sudo rpm -ivh /home/centos/tuned-profiles-nfv-guest-2.8.0-5.el7_4.2.noarch.rpm --nodeps -# Although we do no know how many cores the VM will have when begin deployed for real testing, we already put a number for the -# isolated CPUs so we can start the realtime-virtual-guest profile. If we don't, that command will fail. -# When the VM will be instantiated, the check_kernel_params service will check for the real number of cores available to this VM -# and update the realtime-virtual-guest-variables.conf accordingly. -echo "isolated_cores=1" | sudo tee -a /etc/tuned/realtime-virtual-guest-variables.conf -sudo tuned-adm profile realtime-virtual-guest - -# Install the check_tuned_params service to make sure that the grub cmd line has the right cpus in isolcpu. The actual number of cpu's -# assigned to this VM depends on the flavor used. We don't know at this time what that will be. -sudo cp -r /home/centos/check_prox_system_setup.sh /usr/local/libexec/ -sudo cp -r /home/centos/check-prox-system-setup.service /etc/systemd/system/ -sudo systemctl daemon-reload -sudo systemctl enable check-prox-system-setup.service diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/gen.cfg b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/gen.cfg index fd8eadbf..42cfdc1b 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/gen.cfg +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/gen.cfg @@ -31,7 +31,7 @@ vlan=yes $mbs=8 [defaults] -mempool size=4K +mempool size=8K [global] name=${name} @@ -39,7 +39,7 @@ name=${name} [core 0] mode=master -[core $group1] +[core $gencores] name=p0 task=0 mode=gen @@ -58,8 +58,9 @@ accuracy pos=46 packet id pos=50 signature=0x6789abcd signature pos=56 +;arp update time=1 -[core $group2] +[core $latcores] name=lat task=0 mode=lat @@ -70,4 +71,6 @@ accuracy pos=46 packet id pos=50 signature=0x6789abcd signature pos=56 +accuracy limit nsec=1000000 +;arp update time=1 diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/gen_gw.cfg b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/gen_gw.cfg index 4d5c7076..e819041c 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/gen_gw.cfg +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/gen_gw.cfg @@ -31,7 +31,7 @@ vlan=yes $mbs=8 [defaults] -mempool size=4K +mempool size=8K [global] name=${name} @@ -39,7 +39,7 @@ name=${name} [core 0] mode=master -[core $group1] +[core $gencores] name=p0 task=0 mode=gen @@ -58,8 +58,9 @@ accuracy pos=46 packet id pos=50 signature=0x6789abcd signature pos=56 +;arp update time=1 -[core $group2] +[core $latcores] name=lat task=0 mode=lat @@ -70,3 +71,4 @@ accuracy pos=46 packet id pos=50 signature=0x6789abcd signature pos=56 +;arp update time=1 diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/impair.cfg b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/impair.cfg index c41c479c..8ca9e05d 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/impair.cfg +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/impair.cfg @@ -30,7 +30,7 @@ vlan=yes [defaults] -mempool size=4K +mempool size=8K [global] name=${name} @@ -38,7 +38,7 @@ name=${name} [core 0] mode=master -[core $group1] +[core $impaircores] name=impair task=0 mode=impair diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/impair.test b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/impair.test index ff6624b7..9b633d99 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/impair.test +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/impair.test @@ -16,42 +16,39 @@ [DEFAULT] name = impairTesting -number_of_tests = 1 +number_of_tests = 2 total_number_of_test_machines = 3 -init_code=init_test() -dest_vm = not_used -gw_vm = not_used -script_control = false -group1cores = not_used -group2cores = not_used -group3cores = not_used -drop_rate_treshold = 1 -lat_avg_treshold = 1200 -lat_max_treshold = 2000 -accuracy = 0.01 -startspeed = 10 +prox_socket = true +prox_launch_exit = true [TestM1] name = Generator -machine_index = 1 config_file = gen_gw.cfg gw_vm = 2 dest_vm = 3 -group1cores = [1] -group2cores = [3] -group3cores = [1,3] +gencores = [1] +latcores = [3] +startspeed = 10 [TestM2] name = ImpairGW -machine_index = 2 config_file = impair.cfg -group1cores = [1] +impaircores = [1] [TestM3] name = Swap -machine_index = 3 config_file = swap.cfg -group1cores = [1] +swapcores = [1] + +[BinarySearchParams] +drop_rate_threshold = 0.1 +lat_avg_threshold = 500 +lat_max_threshold = 1000 +accuracy = 0.1 [test1] -cmd=run_impairtest(socks[0],socks[2]) +test=inittest + +[test2] +test=impairtest +packetsize=64 diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/irq.cfg b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/irq.cfg index 304312f2..38e4b966 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/irq.cfg +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/irq.cfg @@ -21,14 +21,14 @@ no-output=no ; disable DPDK debug output [lua] dofile("parameters.lua") -[port 0] +[;port 0] name=p0 [variables] $mbs=8 [defaults] -mempool size=4K +mempool size=8K [global] name=${name} @@ -36,7 +36,7 @@ name=${name} [core 0] mode=master -[core $group1] +[core $irqcores] name=irq task=0 mode=irq diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/irq.test b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/irq.test index d5ba9dff..b8dc706b 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/irq.test +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/irq.test @@ -16,36 +16,17 @@ [DEFAULT] name = BasicSwapTesting -number_of_tests = 2 -total_number_of_test_machines = 2 -init_code= not_used -dest_vm = not_used -gw_vm = not_used -script_control = false -group1cores = not_used -group2cores = not_used -group3cores = not_used -drop_rate_treshold = 1 -lat_avg_treshold = 200 -lat_max_treshold = 1000 -accuracy = 0.01 -startspeed = 10 +number_of_tests = 1 +total_number_of_test_machines = 1 +prox_socket = true +prox_launch_exit = true [TestM1] name = InterruptTesting -machine_index = 1 config_file = irq.cfg -group1cores = [1,2,3] - -[TestM2] -name = InterruptTesting -machine_index = 2 -config_file = irq.cfg -group1cores = [1,2,3] +irqcores = [1,2,3] [test1] -cmd=run_irqtest(socks[0]) -[test2] -cmd=run_irqtest(socks[1]) +test=irqtest diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2framerate.test b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2framerate.test index 68a3fa38..44fefdda 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2framerate.test +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2framerate.test @@ -16,36 +16,27 @@ [DEFAULT] name = L2BasicSwapTesting -number_of_tests = 1 +number_of_tests = 2 total_number_of_test_machines = 2 -init_code=init_test() -dest_vm = not_used -gw_vm = not_used -script_control = false -group1cores = not_used -group2cores = not_used -group3cores = not_used -drop_rate_treshold = 0 -lat_avg_treshold = 100 -lat_max_treshold = 800 -accuracy = 0.1 -startspeed = 100 +prox_socket = true +prox_launch_exit = true [TestM1] name = Generator -machine_index = 1 config_file = l2gen.cfg dest_vm = 2 -script_control = true -group1cores = [1,2,3,4] -group2cores = [5] -group3cores = [1,2,3,4,5] +gencores = [1] +latcores = [3] +startspeed = 10 [TestM2] name = Swap -machine_index = 2 config_file = l2swap.cfg -group1cores = [2] +swapcores = [1] [test1] -cmd=run_max_frame_rate(socks[0],socks[1]) +test=inittest + +[test2] +test=max_frame_rate +packetsizes=[256] diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2gen.cfg b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2gen.cfg index f055c6aa..1469604b 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2gen.cfg +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2gen.cfg @@ -31,7 +31,7 @@ vlan=yes $mbs=8 [defaults] -mempool size=4K +mempool size=8K [global] name=${name} @@ -39,7 +39,7 @@ name=${name} [core 0] mode=master -[core $group1] +[core $gencores] name=p0 task=0 mode=gen @@ -58,7 +58,7 @@ packet id pos=50 signature=0x6789abcd signature pos=56 -[core $group2] +[core $latcores] name=lat task=0 mode=lat diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2swap.cfg b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2swap.cfg index 98246aba..004588c0 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2swap.cfg +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2swap.cfg @@ -29,7 +29,7 @@ tx desc=2048 vlan=yes [defaults] -mempool size=4K +mempool size=8K [global] name=${name} @@ -37,7 +37,7 @@ name=${name} [core 0] mode=master -[core $group1] +[core $swapcores] name=swap task=0 mode=swap diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2zeroloss.test b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2zeroloss.test index 9049877e..04065909 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2zeroloss.test +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l2zeroloss.test @@ -16,40 +16,41 @@ [DEFAULT] name = L2BasicSwapTesting -number_of_tests = 3 +number_of_tests = 4 total_number_of_test_machines = 2 -init_code=init_test() -dest_vm = not_used -gw_vm = not_used -script_control = false -group1cores = not_used -group2cores = not_used -group3cores = not_used -drop_rate_treshold = 0 -lat_avg_treshold = 200 -lat_max_treshold = 1000 -accuracy = 0.1 -startspeed = 10 +prox_socket = true +prox_launch_exit = true [TestM1] name = Generator -machine_index = 1 config_file = l2gen.cfg dest_vm = 2 -script_control = true -group1cores = [1] -group2cores = [3] -group3cores = [1,3] +gencores = [1] +latcores = [3] +startspeed = 10 [TestM2] name = Swap -machine_index = 2 config_file = l2swap.cfg -group1cores = [1] +swapcores = [1] + +[BinarySearchParams] +drop_rate_threshold = 0 +lat_avg_threshold = 500 +lat_max_threshold = 1000 +accuracy = 0.1 + [test1] -cmd=run_speedtest(socks[0],socks[1]) +test=inittest + [test2] -cmd=run_sizetest(socks[0],socks[1]) +test=speedtest +packetsize=64 + [test3] -cmd=run_flowtest(socks[0],socks[1]) +test=sizetest + +[test4] +test=flowtest +packetsize=64 diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l3framerate.test b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l3framerate.test new file mode 100644 index 00000000..21bf8106 --- /dev/null +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/l3framerate.test @@ -0,0 +1,42 @@ +## +## Copyright (c) 2010-2019 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. +## + +[DEFAULT] +name = L3FrameRateTesting +number_of_tests = 2 +total_number_of_test_machines = 2 +prox_socket = true +prox_launch_exit = true + +[TestM1] +name = Generator +config_file = gen.cfg +dest_vm = 2 +gencores = [1] +latcores = [3] +startspeed = 10 + +[TestM2] +name = Swap +config_file = swap.cfg +swapcores = [1] + +[test1] +test=inittest + +[test2] +test=max_frame_rate +packetsizes=[256] diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/prox_ctrl.py b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/prox_ctrl.py index 70395097..3ee28c00 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/prox_ctrl.py +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/prox_ctrl.py @@ -40,8 +40,8 @@ class prox_ctrl(object): def close(self): """Must be called before program termination.""" - for prox in self._proxsock: - prox.quit() +# for prox in self._proxsock: +# prox.quit() children = len(self._children) if children == 0: return @@ -193,7 +193,11 @@ class prox_sock(object): max_lat = max(int(stats[1]),max_lat) avg_lat += int(stats[2]) avg_lat = avg_lat/len(cores) - return min_lat, max_lat, avg_lat + self._send('stats latency(0).used') + used = float(self._recv()) + self._send('stats latency(0).total') + total = float(self._recv()) + return min_lat, max_lat, avg_lat, (used/total) def irq_stats(self, core, bucket, task=0): self._send('stats task.core(%s).task(%s).irq(%s)' % (core, task, bucket)) diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/rapidVMs.vms b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/rapidVMs.vms index dc22a9c5..d18184d6 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/rapidVMs.vms +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/rapidVMs.vms @@ -17,13 +17,13 @@ [DEFAULT] total_number_of_vms=3 -flavor_info=--ram 4096 --disk 20 --vcpus 4 +flavor_info=--ram 4096 --disk 40 --vcpus 4 ;flavor_meta_data=--property hw:mem_page_size=large --property hw:cpu_policy=dedicated --property hw:cpu_thread_policy=isolate --property hw:numa_nodes=1 --property hw:numa_cpus.0=0,1,2,3 --property hw:numa_mempolicy=strict --property hw:numa_mem.0=4096 ;flavor_meta_data=--property hw:mem_page_size=large --property hw:cpu_policy=dedicated --property hw:cpu_thread_policy=isolate -;flavor_meta_data=--property hw:mem_page_size=large --property hw:cpu_policy=dedicated -flavor_meta_data=--property hw:mem_page_size=large --property hw:cpu_policy=dedicated --property hw:cpu_realtime=yes --property hw:cpu_realtime_mask=^0 +flavor_meta_data=--property hw:mem_page_size=large --property hw:cpu_policy=dedicated +;flavor_meta_data=--property hw:mem_page_size=large --property hw:cpu_policy=dedicated --property hw:cpu_realtime=yes --property hw:cpu_realtime_mask=^0 ;boot_info=--availability-zone nova --security-group default -boot_info=--availability-zone L27 --security-group default +boot_info=--availability-zone nova --security-group prox SRIOV_port=NO [VM1] diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/runrapid.py b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/runrapid.py index e625c4d3..3b0eeb8b 100755 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/runrapid.py +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/runrapid.py @@ -34,9 +34,10 @@ import ast import atexit import csv -version="19.1.10" +version="19.4.15" env = "rapid" #Default string for environment test = "basicrapid" #Default string for test +machine_map_file = "MachineMap" #Default string for machine map file loglevel="DEBUG" # sets log level for writing to file runtime=10 # time in seconds for 1 test run configonly = False # IF True, the system will upload all the necessary config fiels to the VMs, but not start PROX and the actual testing @@ -45,6 +46,7 @@ def usage(): print("usage: runrapid [--version] [-v]") print(" [--env ENVIRONMENT_NAME]") print(" [--test TEST_NAME]") + print(" [--map MACHINE_MAP_FILE]") print(" [--runtime TIME_FOR_TEST]") print(" [--configonly False|True]") print(" [--log DEBUG|INFO|WARNING|ERROR|CRITICAL]") @@ -56,6 +58,7 @@ def usage(): print(" -v, --version Show program's version number and exit") print(" --env ENVIRONMENT_NAME Parameters will be read from ENVIRONMENT_NAME.env Default is %s."%env) print(" --test TEST_NAME Test cases will be read from TEST_NAME.test Default is %s."%test) + print(" --map MACHINE_MAP_FILE Machine mapping will be read from MACHINE_MAP_FILE.cfg Default is %s."%machine_map_file) print(" --runtime Specify time in seconds for 1 test run") print(" --configonly If True, only upload all config files to the VMs, do not run the tests. Default is %s."%configonly) print(" --log Specify logging level for log file output, screen output level is hard coded") @@ -63,7 +66,7 @@ def usage(): print("") try: - opts, args = getopt.getopt(sys.argv[1:], "vh", ["version","help", "env=", "test=","runtime=","configonly=","log="]) + opts, args = getopt.getopt(sys.argv[1:], "vh", ["version","help", "env=", "test=", "map=", "runtime=","configonly=","log="]) except getopt.GetoptError as err: print("===========================================") print(str(err)) @@ -86,6 +89,9 @@ for opt, arg in opts: if opt in ("--test"): test = arg print ("Using '"+test+".test' for test case definition") + if opt in ("--map"): + machine_map_file = arg + print ("Using '"+machine_map_file+".cfg' for machine mapping") if opt in ("--runtime"): runtime = arg print ("Runtime: "+ runtime) @@ -131,8 +137,7 @@ console_handler.setFormatter(screen_formatter) # create a file handler # and set its log level to DEBUG # -log_file = 'RUN' +env+'.'+test+'.log' -data_file = 'RUN' +env+'.'+test+'.csv' +log_file = 'RUN{}.{}.log'.format(env,test) file_handler = logging.handlers.RotatingFileHandler(log_file, backupCount=10) #file_handler = log.handlers.TimedRotatingFileHandler(log_file, 'D', 1, 5) file_handler.setLevel(numeric_level) @@ -203,8 +208,24 @@ def run_iteration(gensock,sutsock): if sutsock!='none': old_sut_rx, old_sut_tx, old_sut_drop, old_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores) old_rx, old_tx, old_drop, old_tsc, tsc_hz = gensock.core_stats(genstatcores) - time.sleep(float(runtime)) - lat_min, lat_max, lat_avg = gensock.lat_stats(latcores) + # Measure latency statistics per second + n_loops = 0 + lat_min = 0 + lat_max = 0 + lat_avg = 0 + used_avg = 0 + while n_loops < float(runtime): + n_loops +=1 + time.sleep(1) + lat_min_sample, lat_max_sample, lat_avg_sample, used_sample = gensock.lat_stats(latcores) + if lat_min > lat_min_sample: + lat_min = lat_min_sample + if lat_max < lat_max_sample: + lat_max = lat_max_sample + lat_avg = lat_avg + lat_avg_sample + used_avg = used_avg + used_sample + lat_avg = lat_avg / n_loops + used_avg = used_avg / n_loops # Get statistics after some execution time new_rx, new_tx, new_drop, new_tsc, tsc_hz = gensock.core_stats(genstatcores) if sutsock!='none': @@ -233,21 +254,9 @@ def run_iteration(gensock,sutsock): if (tx == 0): log.critical("TX = 0. Test interrupted since no packet has been sent.") raise Exception("TX = 0") - return(pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max,abs_dropped,(abs_new_tx - abs_old_tx)) + return(pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max,abs_dropped,(abs_new_tx - abs_old_tx),lat_min,used_avg) def new_speed(speed,minspeed,maxspeed,success): - # Following calculates the ratio for the new speed to be applied - # On the Y axis, we will find the ratio, a number between 0 and 1 - # On the x axis, we find the % of dropped packets, a number between 0 and 100 - # 2 lines are drawn and we take the minumun of these lines to calculate the ratio - # One line goes through (0,y0) and (p,q) - # The second line goes through (p,q) and (100,y100) -# y0=0.99 -# y100=0.1 -# p=1 -# q=.99 -# ratio = min((q-y0)/p*drop_rate+y0,(q-y100)/(p-100)*drop_rate+q-p*(q-y100)/(p-100)) -# return (int(speed*ratio*100)+0.5)/100.0 if success: minspeed = speed else: @@ -261,7 +270,7 @@ def get_pps(speed,size): def run_speedtest(gensock,sutsock): maxspeed = speed = STARTSPEED minspeed = 0 - size=175 + size=PACKETSIZE-4 attempts = 0 log.info("+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+") log.info("| Generator is sending UDP (1 flow) packets ("+ '{:>5}'.format(size+4) +" bytes) to SUT. SUT sends packets back |") @@ -273,18 +282,23 @@ def run_speedtest(gensock,sutsock): gensock.set_value(gencores,0,16,(size-14),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS) gensock.set_value(gencores,0,38,(size-34),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20) # This will only work when using sending UDP packets. For different protocols and ethernet types, we would need a different calculation + gensock.start(latcores) while (maxspeed-minspeed > ACCURACY): attempts += 1 print('Measurement ongoing at speed: ' + str(round(speed,2)) + '% ',end='\r') sys.stdout.flush() # Start generating packets at requested speed (in % of a 10Gb/s link) - gensock.speed(speed, gencores) + gensock.speed(speed / len(gencores), gencores) time.sleep(1) # Get statistics now that the generation is stable and initial ARP messages are dealt with. - pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx = run_iteration(gensock,sutsock) + pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx, lat_min, lat_used = run_iteration(gensock,sutsock) drop_rate = 100.0*abs_dropped/abs_tx + if lat_used < 0.95: + lat_warning = bcolors.FAIL + ' Potential latency accuracy problem: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC + else: + lat_warning = '' if ((get_pps(speed,size) - pps_tx)/get_pps(speed,size))<0.001 and ((drop_rate < DROP_RATE_TRESHOLD) or (abs_dropped==DROP_RATE_TRESHOLD ==0)) and (lat_avg< LAT_AVG_TRESHOLD) and (lat_max < LAT_MAX_TRESHOLD): - log.info('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(pps_tx) +' Mpps | ' + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+ '{:>9.0f}'.format(lat_avg)+' us | '+ '{:>9.0f}'.format(lat_max)+' us | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% | SUCCESS |') + log.info('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(pps_tx) +' Mpps | ' + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+ '{:>9.0f}'.format(lat_avg)+' us | '+ '{:>9.0f}'.format(lat_max)+' us | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% | SUCCESS |'+lat_warning) endspeed = speed endpps_req_tx = pps_req_tx endpps_tx = pps_tx @@ -294,6 +308,7 @@ def run_speedtest(gensock,sutsock): endlat_max = lat_max endabs_dropped = abs_dropped enddrop_rate = drop_rate + endwarning = lat_warning success = True else: abs_drop_rate_prefix = bcolors.ENDC @@ -315,31 +330,54 @@ def run_speedtest(gensock,sutsock): speed_prefix = bcolors.ENDC else: speed_prefix = bcolors.FAIL - log.info('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% '+speed_prefix +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | ' + '{:>9.3f}'.format(pps_tx) +' Mpps | '+ bcolors.ENDC + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+lat_avg_prefix+ '{:>9.0f}'.format(lat_avg)+' us | '+lat_max_prefix+ '{:>9.0f}'.format(lat_max)+' us | '+ abs_drop_rate_prefix + '{:>14d}'.format(abs_dropped)+drop_rate_prefix+ ' |''{:>9.2f}'.format(drop_rate)+bcolors.ENDC+ '% | FAILED |') + log.info('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% '+speed_prefix +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | ' + '{:>9.3f}'.format(pps_tx) +' Mpps | '+ bcolors.ENDC + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+lat_avg_prefix+ '{:>9.0f}'.format(lat_avg)+' us | '+lat_max_prefix+ '{:>9.0f}'.format(lat_max)+' us | '+ abs_drop_rate_prefix + '{:>14d}'.format(abs_dropped)+drop_rate_prefix+ ' |''{:>9.2f}'.format(drop_rate)+bcolors.ENDC+ '% | FAILED |'+lat_warning) success = False speed,minspeed,maxspeed = new_speed(speed,minspeed,maxspeed,success) if endpps_sut_tx_str <> 'NO_RESULTS': log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+------------+") - log.info('|{:>7}'.format('END')+" | " + '{:>5.1f}'.format(endspeed) + '% ' +'{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(endpps_rx)+' Mpps | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+ '{:>9.0f}'.format(endlat_max)+' us | '+'{:>14d}'.format(endabs_dropped)+ ' |''{:>9.2f}'.format(enddrop_rate)+ '% | SUCCESS |') + log.info('|{:>7}'.format('END')+" | " + '{:>5.1f}'.format(endspeed) + '% ' +'{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(endpps_rx)+' Mpps | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+ '{:>9.0f}'.format(endlat_max)+' us | '+'{:>14d}'.format(endabs_dropped)+ ' |''{:>9.2f}'.format(enddrop_rate)+ '% | SUCCESS |'+endwarning) log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+------------+") + writer.writerow({'flow':'1','size':(size+4),'endspeed':endspeed,'endspeedpps':get_pps(endspeed,size),'endpps_req_tx':endpps_req_tx,'endpps_tx':endpps_tx,'endpps_sut_tx_str':endpps_sut_tx_str,'endpps_rx':endpps_rx,'endlat_avg':endlat_avg,'endlat_max':endlat_max,'endabs_dropped':endabs_dropped,'enddrop_rate':enddrop_rate}) else: log.info('| Speed 0 or close to 0') + gensock.stop(latcores) def run_flowtest(gensock,sutsock): + size=PACKETSIZE-4 log.info("+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+") - log.info("| UDP, 64 bytes, different number of flows by randomizing SRC & DST UDP port |") + log.info("| UDP, "+ '{:>5}'.format(size+4) +" bytes, different number of flows by randomizing SRC & DST UDP port |") log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+") log.info("| Flows | Speed requested | Sent to NIC | Sent by Gen | Forward by SUT | Rec. by Gen | Avg. Latency | Max. Latency | Packets Lost | Loss Ratio |") log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+") - size=60 # To generate a desired number of flows, PROX will randomize the bits in source and destination ports, as specified by the bit masks in the flows variable. - flows={128:['1000000000000XXX','100000000000XXXX'],1024:['10000000000XXXXX','10000000000XXXXX'],8192:['1000000000XXXXXX','100000000XXXXXXX'],65535:['10000000XXXXXXXX','10000000XXXXXXXX'],524280:['1000000XXXXXXXXX','100000XXXXXXXXXX']} -# flows={524280:['1000000XXXXXXXXX','100000XXXXXXXXXX']} + flows={\ + 1: ['1000000000000000','1000000000000000'],\ + 2: ['1000000000000000','100000000000000X'],\ + 4: ['100000000000000X','100000000000000X'],\ + 8: ['100000000000000X','10000000000000XX'],\ + 16: ['10000000000000XX','10000000000000XX'],\ + 32: ['10000000000000XX','1000000000000XXX'],\ + 64: ['1000000000000XXX','1000000000000XXX'],\ + 128: ['1000000000000XXX','100000000000XXXX'],\ + 256: ['100000000000XXXX','100000000000XXXX'],\ + 512: ['100000000000XXXX','10000000000XXXXX'],\ + 1024: ['10000000000XXXXX','10000000000XXXXX'],\ + 2048: ['10000000000XXXXX','1000000000XXXXXX'],\ + 4096: ['1000000000XXXXXX','1000000000XXXXXX'],\ + 8192: ['1000000000XXXXXX','100000000XXXXXXX'],\ + 16384: ['100000000XXXXXXX','100000000XXXXXXX'],\ + 32768: ['100000000XXXXXXX','10000000XXXXXXXX'],\ + 65535: ['10000000XXXXXXXX','10000000XXXXXXXX'],\ + 131072: ['10000000XXXXXXXX','1000000XXXXXXXXX'],\ + 262144: ['1000000XXXXXXXXX','1000000XXXXXXXXX'],\ + 524280: ['1000000XXXXXXXXX','100000XXXXXXXXXX'],\ + 1048576:['100000XXXXXXXXXX','100000XXXXXXXXXX'],} gensock.set_size(gencores,0,size) # This is setting the frame size gensock.set_value(gencores,0,16,(size-14),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS) gensock.set_value(gencores,0,38,(size-34),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20) # This will only work when using sending UDP packets. For different protocls and ehternet types, we would need a differnt calculation - for flow_number in sorted(flows.iterkeys()): + gensock.start(latcores) + for flow_number in flow_size_list: attempts = 0 gensock.reset_stats() if sutsock!='none': @@ -355,13 +393,17 @@ def run_flowtest(gensock,sutsock): print(str(flow_number)+' flows: Measurement ongoing at speed: ' + str(round(speed,2)) + '% ',end='\r') sys.stdout.flush() # Start generating packets at requested speed (in % of a 10Gb/s link) - gensock.speed(speed, gencores) + gensock.speed(speed / len(gencores), gencores) time.sleep(1) # Get statistics now that the generation is stable and initial ARP messages are dealt with - pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx = run_iteration(gensock,sutsock) + pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx, lat_min, lat_used = run_iteration(gensock,sutsock) drop_rate = 100.0*abs_dropped/abs_tx + if lat_used < 0.95: + lat_warning = bcolors.FAIL + ' Potential latency accuracy problem: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC + else: + lat_warning = '' if ((get_pps(speed,size) - pps_tx)/get_pps(speed,size))<0.001 and ((drop_rate < DROP_RATE_TRESHOLD) or (abs_dropped==DROP_RATE_TRESHOLD ==0)) and (lat_avg< LAT_AVG_TRESHOLD) and (lat_max < LAT_MAX_TRESHOLD): - log.debug('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(pps_tx) +' Mpps | ' + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+ '{:>9.0f}'.format(lat_avg)+' us | '+ '{:>9.0f}'.format(lat_max)+' us | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% | SUCCESS |') + log.debug('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(pps_tx) +' Mpps | ' + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+ '{:>9.0f}'.format(lat_avg)+' us | '+ '{:>9.0f}'.format(lat_max)+' us | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% | SUCCESS |'+lat_warning) endspeed = speed endpps_req_tx = pps_req_tx endpps_tx = pps_tx @@ -371,6 +413,7 @@ def run_flowtest(gensock,sutsock): endlat_max = lat_max endabs_dropped = abs_dropped enddrop_rate = drop_rate + endwarning = lat_warning success = True else: abs_drop_rate_prefix = bcolors.ENDC @@ -392,15 +435,16 @@ def run_flowtest(gensock,sutsock): speed_prefix = bcolors.ENDC else: speed_prefix = bcolors.FAIL - log.debug('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% '+speed_prefix +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | ' + '{:>9.3f}'.format(pps_tx) +' Mpps | '+ bcolors.ENDC + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+lat_avg_prefix+ '{:>9.0f}'.format(lat_avg)+' us | '+lat_max_prefix+ '{:>9.0f}'.format(lat_max)+' us | '+ abs_drop_rate_prefix + '{:>14d}'.format(abs_dropped)+drop_rate_prefix+ ' |''{:>9.2f}'.format(drop_rate)+bcolors.ENDC+ '% | FAILED |') + log.debug('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% '+speed_prefix +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | ' + '{:>9.3f}'.format(pps_tx) +' Mpps | '+ bcolors.ENDC + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+lat_avg_prefix+ '{:>9.0f}'.format(lat_avg)+' us | '+lat_max_prefix+ '{:>9.0f}'.format(lat_max)+' us | '+ abs_drop_rate_prefix + '{:>14d}'.format(abs_dropped)+drop_rate_prefix+ ' |''{:>9.2f}'.format(drop_rate)+bcolors.ENDC+ '% | FAILED |'+lat_warning) success = False speed,minspeed,maxspeed = new_speed(speed,minspeed,maxspeed,success) if endpps_sut_tx_str <> 'NO_RESULTS': - log.info('|{:>7}'.format(str(flow_number))+" | " + '{:>5.1f}'.format(endspeed) + '% ' +'{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(endpps_rx)+' Mpps | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+ '{:>9.0f}'.format(endlat_max)+' us | '+ '{:>14d}'.format(endabs_dropped)+ ' |'+'{:>9.2f}'.format(enddrop_rate)+ '% |') + log.info('|{:>7}'.format(str(flow_number))+" | " + '{:>5.1f}'.format(endspeed) + '% ' +'{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(endpps_rx)+' Mpps | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+ '{:>9.0f}'.format(endlat_max)+' us | '+ '{:>14d}'.format(endabs_dropped)+ ' |'+'{:>9.2f}'.format(enddrop_rate)+ '% |'+endwarning) log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+") writer.writerow({'flow':flow_number,'size':(size+4),'endspeed':endspeed,'endspeedpps':get_pps(endspeed,size),'endpps_req_tx':endpps_req_tx,'endpps_tx':endpps_tx,'endpps_sut_tx_str':endpps_sut_tx_str,'endpps_rx':endpps_rx,'endlat_avg':endlat_avg,'endlat_max':endlat_max,'endabs_dropped':endabs_dropped,'enddrop_rate':enddrop_rate}) else: log.info('|{:>7}'.format(str(flow_number))+" | Speed 0 or close to 0") + gensock.stop(latcores) def run_sizetest(gensock,sutsock): log.info("+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+") @@ -408,11 +452,9 @@ def run_sizetest(gensock,sutsock): log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+") log.info("| Pktsize| Speed requested | Sent to NIC | Sent by Gen | Forward by SUT | Rec. by Gen | Avg. Latency | Max. Latency | Packets Lost | Loss Ratio |") log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+") - # PROX will use different packet sizes as defined in sizes[] - sizes=[1496,1020,508,252,124,60] -# sizes=[1020,508,252,124,60] -# sizes=[124,60] - for size in sizes: + gensock.start(latcores) + for size in packet_size_list: + size = size-4 attempts = 0 gensock.reset_stats() if sutsock!='none': @@ -429,12 +471,16 @@ def run_sizetest(gensock,sutsock): print(str(size+4)+' bytes: Measurement ongoing at speed: ' + str(round(speed,2)) + '% ',end='\r') sys.stdout.flush() # Start generating packets at requested speed (in % of a 10Gb/s link) - gensock.speed(speed, gencores) + gensock.speed(speed / len(gencores), gencores) # Get statistics now that the generation is stable and initial ARP messages are dealt with - pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx = run_iteration(gensock,sutsock) + pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx, lat_min, lat_used = run_iteration(gensock,sutsock) drop_rate = 100.0*abs_dropped/abs_tx + if lat_used < 0.95: + lat_warning = bcolors.FAIL + ' Potential latency accuracy problem: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC + else: + lat_warning = '' if ((get_pps(speed,size) - pps_tx)/get_pps(speed,size))<0.001 and ((drop_rate < DROP_RATE_TRESHOLD) or (abs_dropped==DROP_RATE_TRESHOLD ==0)) and (lat_avg< LAT_AVG_TRESHOLD) and (lat_max < LAT_MAX_TRESHOLD): - log.debug('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(pps_tx) +' Mpps | ' + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+ '{:>9.0f}'.format(lat_avg)+' us | '+ '{:>9.0f}'.format(lat_max)+' us | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% | SUCCESS |') + log.debug('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(pps_tx) +' Mpps | ' + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+ '{:>9.0f}'.format(lat_avg)+' us | '+ '{:>9.0f}'.format(lat_max)+' us | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% | SUCCESS |'+lat_warning) endspeed = speed endpps_req_tx = pps_req_tx endpps_tx = pps_tx @@ -444,6 +490,7 @@ def run_sizetest(gensock,sutsock): endlat_max = lat_max endabs_dropped = abs_dropped enddrop_rate = drop_rate + endwarning = lat_warning success = True else: abs_drop_rate_prefix = bcolors.ENDC @@ -465,113 +512,129 @@ def run_sizetest(gensock,sutsock): speed_prefix = bcolors.ENDC else: speed_prefix = bcolors.FAIL - log.debug('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% '+speed_prefix +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | ' + '{:>9.3f}'.format(pps_tx) +' Mpps | '+ bcolors.ENDC + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+lat_avg_prefix+ '{:>9.0f}'.format(lat_avg)+' us | '+lat_max_prefix+ '{:>9.0f}'.format(lat_max)+' us | '+ abs_drop_rate_prefix + '{:>14d}'.format(abs_dropped)+drop_rate_prefix+ ' |''{:>9.2f}'.format(drop_rate)+bcolors.ENDC+ '% | FAILED |') + log.debug('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% '+speed_prefix +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | ' + '{:>9.3f}'.format(pps_tx) +' Mpps | '+ bcolors.ENDC + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+lat_avg_prefix+ '{:>9.0f}'.format(lat_avg)+' us | '+lat_max_prefix+ '{:>9.0f}'.format(lat_max)+' us | '+ abs_drop_rate_prefix + '{:>14d}'.format(abs_dropped)+drop_rate_prefix+ ' |''{:>9.2f}'.format(drop_rate)+bcolors.ENDC+ '% | FAILED |'+ lat_warning) success = False speed,minspeed,maxspeed = new_speed(speed,minspeed,maxspeed,success) if endpps_sut_tx_str <> 'NO_RESULTS': - log.info('|{:>7}'.format(size+4)+" | " + '{:>5.1f}'.format(endspeed) + '% ' +'{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(endpps_rx)+' Mpps | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+'{:>9.0f}'.format(endlat_max)+' us | '+ '{:>14d}'.format(endabs_dropped)+ ' |'+'{:>9.2f}'.format(enddrop_rate)+ '% |') + log.info('|{:>7}'.format(size+4)+" | " + '{:>5.1f}'.format(endspeed) + '% ' +'{:>6.3f}'.format(get_pps(endspeed,size)) + ' Mpps | '+ '{:>9.3f}'.format(endpps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(endpps_tx) +' Mpps | ' + '{:>9}'.format(endpps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(endpps_rx)+' Mpps | '+ '{:>9.0f}'.format(endlat_avg)+' us | '+'{:>9.0f}'.format(endlat_max)+' us | '+ '{:>14d}'.format(endabs_dropped)+ ' |'+'{:>9.2f}'.format(enddrop_rate)+ '% |'+ endwarning) log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+") writer.writerow({'flow':'1','size':(size+4),'endspeed':endspeed,'endspeedpps':get_pps(endspeed,size),'endpps_req_tx':endpps_req_tx,'endpps_tx':endpps_tx,'endpps_sut_tx_str':endpps_sut_tx_str,'endpps_rx':endpps_rx,'endlat_avg':endlat_avg,'endlat_max':endlat_max,'endabs_dropped':endabs_dropped,'enddrop_rate':enddrop_rate}) else: log.debug('|{:>7}'.format(str(size))+" | Speed 0 or close to 0") - + gensock.stop(latcores) def run_max_frame_rate(gensock,sutsock): - log.info("+-----------------------------------------------------------------------------------------------------------------------------------------------------------+") - log.info("| UDP, 1 flow, different packet sizes |") - log.info("+-----+------------------+-------------+-------------+-------------+-------------+-------------+-------------+-----------+-----------+---------+------------+") - log.info("|Pktsz| Speed requested | Sent to NIC | Sent by Gen | Fwrd by SUT | Rec. by Gen | Avg. Latency| Max. Latency| Sent | Received | Lost | Total Lost |") - log.info("+-----+------------------+-------------+-------------+-------------+-------------+-------------+-------------+-----------+-----------+---------+------------+") - # PROX will use different packet sizes as defined in sizes[] - sizes=[1496,1020,508,252,124,60] - sleep_time = 3 - for size in sizes: - # Sleep_time is needed to be able to do accurate measurements to check for packet loss. We need to make this time large enough so that we do not take the first measurement while some packets from the previous tests migth still be in flight - time.sleep(sleep_time) - gensock.reset_stats() - if sutsock!='none': - sutsock.reset_stats() - gensock.set_size(gencores,0,size) # This is setting the frame size - gensock.set_value(gencores,0,16,(size-14),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS) - gensock.set_value(gencores,0,38,(size-34),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20) - # This will only work when using sending UDP packets. For different protocls and ehternet types, we would need a differnt calculation - pps_sut_tx_str = 'NO_RESULTS' - speed = STARTSPEED - # Start generating packets at requested speed (in % of a 10Gb/s link) - gensock.speed(speed / len(gencores), gencores) - duration = float(runtime) - first = 1 - tot_drop = 0 - if sutsock!='none': - old_sut_rx, old_sut_tx, old_sut_drop, old_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores) - old_rx, old_tx, old_drop, old_tsc, tsc_hz = gensock.core_stats(genstatcores) - gensock.start(gencores) - while (duration > 0): - duration = duration - 1 - time.sleep(1) - lat_min, lat_max, lat_avg = gensock.lat_stats(latcores) - # Get statistics after some execution time - new_rx, new_tx, new_drop, new_tsc, tsc_hz = gensock.core_stats(genstatcores) - if sutsock!='none': - new_sut_rx, new_sut_tx, new_sut_drop, new_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores) - drop = new_drop-old_drop # drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM - rx = new_rx - old_rx # rx is all packets received by the nop task = all packets received in the gen VM - tx = new_tx - old_tx # tx is all generated packets actually accepted by the interface - tsc = new_tsc - old_tsc # time difference between the 2 measurements, expressed in cycles. - old_drop = new_drop - old_rx = new_rx - old_tx = new_tx - old_tsc = new_tsc - pps_req_tx = (tx+drop-rx)*tsc_hz*1.0/(tsc*1000000) - pps_tx = tx*tsc_hz*1.0/(tsc*1000000) - pps_rx = rx*tsc_hz*1.0/(tsc*1000000) - if sutsock!='none': - sut_rx = new_sut_rx - old_sut_rx - sut_tx = new_sut_tx - old_sut_tx - sut_tsc = new_sut_tsc - old_sut_tsc - old_sut_tx = new_sut_tx - old_sut_rx = new_sut_rx - old_sut_tsc= new_sut_tsc - pps_sut_tx = sut_tx*sut_tsc_hz*1.0/(sut_tsc*1000000) - pps_sut_tx_str = '{:>7.3f}'.format(pps_sut_tx) - else: - pps_sut_tx = 0 - pps_sut_tx_str = 'NO MEAS.' - if (tx == 0): - log.critical("TX = 0. Test interrupted since no packet has been sent.") - raise Exception("TX = 0") - tot_drop = tot_drop + tx - rx - - if pps_sut_tx_str <> 'NO_RESULTS': - # First second mpps are not valid as there is no alignement between time the generator is started and per seconds stats - if (first): - log.info('|{:>4}'.format(size+4)+" |" + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps|'+' |' +' |' +' |'+ ' |'+ '{:>8.0f}'.format(lat_avg)+' us |'+'{:>8.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | '+ '{:>9.0f}'.format(rx) + ' | '+ '{:>7.0f}'.format(tx-rx) + ' | '+'{:>7.0f}'.format(tot_drop) +' | ') - else: - log.info('|{:>4}'.format(size+4)+" |" + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps|'+ '{:>7.3f}'.format(pps_req_tx)+' Mpps |'+ '{:>7.3f}'.format(pps_tx) +' Mpps |' + '{:>7}'.format(pps_sut_tx_str) +' Mpps |'+ '{:>7.3f}'.format(pps_rx)+' Mpps |'+ '{:>8.0f}'.format(lat_avg)+' us |'+'{:>8.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | '+ '{:>9.0f}'.format(rx) + ' | '+ '{:>7.0f}'.format(tx-rx) + ' | '+ '{:>7.0f}'.format(tot_drop) +' | ') + log.info("+-----------------------------------------------------------------------------------------------------------------------------------------------------------+") + log.info("| UDP, 1 flow, different packet sizes |") + log.info("+-----+------------------+-------------+-------------+-------------+-------------+-------------+-------------+-----------+-----------+---------+------------+") + log.info("|Pktsz| Speed requested | Sent to NIC | Sent by Gen | Fwrd by SUT | Rec. by Gen | Avg. Latency| Max. Latency| Sent | Received | Lost | Total Lost |") + log.info("+-----+------------------+-------------+-------------+-------------+-------------+-------------+-------------+-----------+-----------+---------+------------+") + sleep_time = 3 + gensock.start(latcores) + for size in packet_size_list: + # Sleep_time is needed to be able to do accurate measurements to check for packet loss. We need to make this time large enough so that we do not take the first measurement while some packets from the previous tests migth still be in flight + time.sleep(sleep_time) + size = size-4 + gensock.reset_stats() + if sutsock!='none': + sutsock.reset_stats() + gensock.set_size(gencores,0,size) # This is setting the frame size + gensock.set_value(gencores,0,16,(size-14),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS) + gensock.set_value(gencores,0,38,(size-34),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20) + # This will only work when using sending UDP packets. For different protocls and ehternet types, we would need a differnt calculation + pps_sut_tx_str = 'NO_RESULTS' + speed = STARTSPEED + # Start generating packets at requested speed (in % of a 10Gb/s link) + gensock.speed(speed / len(gencores), gencores) + duration = float(runtime) + first = 1 + tot_drop = 0 + if sutsock!='none': + old_sut_rx, old_sut_tx, old_sut_drop, old_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores) + old_rx, old_tx, old_drop, old_tsc, tsc_hz = gensock.core_stats(genstatcores) + gensock.start(gencores) + while (duration > 0): + time.sleep(0.5) + lat_min, lat_max, lat_avg, lat_used = gensock.lat_stats(latcores) + if lat_used < 0.95: + lat_warning = bcolors.FAIL + ' Potential latency accuracy problem: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC else: - log.debug('|{:>7}'.format(str(size))+" | Speed 0 or close to 0") - first = 0 - if (duration <= 0): - #Stop generating - gensock.stop(gencores) - time.sleep(sleep_time) - lat_min, lat_max, lat_avg = gensock.lat_stats(latcores) - # Get statistics after some execution time - new_rx, new_tx, new_drop, new_tsc, tsc_hz = gensock.core_stats(genstatcores) - if sutsock!='none': - new_sut_rx, new_sut_tx, new_sut_drop, new_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores) - drop = new_drop-old_drop # drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM - rx = new_rx - old_rx # rx is all packets received by the nop task = all packets received in the gen VM - tx = new_tx - old_tx # tx is all generated packets actually accepted by the interface - tsc = new_tsc - old_tsc # time difference between the 2 measurements, expressed in cycles. - tot_drop = tot_drop + tx - rx - if sutsock!='none': - sut_rx = new_sut_rx - old_sut_rx - sut_tx = new_sut_tx - old_sut_tx - sut_tsc = new_sut_tsc - old_sut_tsc - if pps_sut_tx_str <> 'NO_RESULTS': - log.info('|{:>4}'.format(size+4)+" |" + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps|'+' |' +' |' +' |'+ ' |'+ '{:>8.0f}'.format(lat_avg)+' us |'+'{:>8.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | '+ '{:>9.0f}'.format(rx) + ' | '+ '{:>7.0f}'.format(tx-rx) + ' | '+ '{:>7.0f}'.format(tot_drop) +' | ') - log.info("+-----+------------------+-------------+-------------+-------------+-------------+-------------+-------------+-----------+-----------+---------+------------+") + lat_warning = '' + # Get statistics after some execution time + new_rx, new_tx, new_drop, new_tsc, tsc_hz = gensock.core_stats(genstatcores) + if sutsock!='none': + new_sut_rx, new_sut_tx, new_sut_drop, new_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores) + drop = new_drop-old_drop # drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM + rx = new_rx - old_rx # rx is all packets received by the nop task = all packets received in the gen VM + tx = new_tx - old_tx # tx is all generated packets actually accepted by the interface + tsc = new_tsc - old_tsc # time difference between the 2 measurements, expressed in cycles. + if tsc == 0 : + continue + if sutsock!='none': + sut_rx = new_sut_rx - old_sut_rx + sut_tx = new_sut_tx - old_sut_tx + sut_tsc = new_sut_tsc - old_sut_tsc + if sut_tsc == 0 : + continue + duration = duration - 1 + old_drop = new_drop + old_rx = new_rx + old_tx = new_tx + old_tsc = new_tsc + pps_req_tx = (tx+drop-rx)*tsc_hz*1.0/(tsc*1000000) + pps_tx = tx*tsc_hz*1.0/(tsc*1000000) + pps_rx = rx*tsc_hz*1.0/(tsc*1000000) + if sutsock!='none': + old_sut_tx = new_sut_tx + old_sut_rx = new_sut_rx + old_sut_tsc= new_sut_tsc + pps_sut_tx = sut_tx*sut_tsc_hz*1.0/(sut_tsc*1000000) + pps_sut_tx_str = '{:>7.3f}'.format(pps_sut_tx) + else: + pps_sut_tx = 0 + pps_sut_tx_str = 'NO MEAS.' + if (tx == 0): + log.critical("TX = 0. Test interrupted since no packet has been sent.") + raise Exception("TX = 0") + tot_drop = tot_drop + tx - rx + + if pps_sut_tx_str <> 'NO_RESULTS': + # First second mpps are not valid as there is no alignement between time the generator is started and per seconds stats + if (first): + log.info('|{:>4}'.format(size+4)+" |" + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps|'+' |' +' |' +' |'+ ' |'+ '{:>8.0f}'.format(lat_avg)+' us |'+'{:>8.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | '+ '{:>9.0f}'.format(rx) + ' | '+ '{:>7.0f}'.format(tx-rx) + ' | '+'{:>7.0f}'.format(tot_drop) +' |'+lat_warning) + else: + log.info('|{:>4}'.format(size+4)+" |" + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps|'+ '{:>7.3f}'.format(pps_req_tx)+' Mpps |'+ '{:>7.3f}'.format(pps_tx) +' Mpps |' + '{:>7}'.format(pps_sut_tx_str) +' Mpps |'+ '{:>7.3f}'.format(pps_rx)+' Mpps |'+ '{:>8.0f}'.format(lat_avg)+' us |'+'{:>8.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | '+ '{:>9.0f}'.format(rx) + ' | '+ '{:>7.0f}'.format(tx-rx) + ' | '+ '{:>7.0f}'.format(tot_drop) +' |'+lat_warning) + else: + log.debug('|{:>7}'.format(str(size))+" | Speed 0 or close to 0") + first = 0 + if (duration <= 0): + #Stop generating + gensock.stop(gencores) + time.sleep(sleep_time) + lat_min, lat_max, lat_avg, lat_used = gensock.lat_stats(latcores) + if lat_used < 0.95: + lat_warning = bcolors.FAIL + ' Potential latency accuracy problem: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC + else: + lat_warning = '' + # Get statistics after some execution time + new_rx, new_tx, new_drop, new_tsc, tsc_hz = gensock.core_stats(genstatcores) + if sutsock!='none': + new_sut_rx, new_sut_tx, new_sut_drop, new_sut_tsc, sut_tsc_hz = sutsock.core_stats(sutstatcores) + drop = new_drop-old_drop # drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM + rx = new_rx - old_rx # rx is all packets received by the nop task = all packets received in the gen VM + tx = new_tx - old_tx # tx is all generated packets actually accepted by the interface + tsc = new_tsc - old_tsc # time difference between the 2 measurements, expressed in cycles. + tot_drop = tot_drop + tx - rx + if sutsock!='none': + sut_rx = new_sut_rx - old_sut_rx + sut_tx = new_sut_tx - old_sut_tx + sut_tsc = new_sut_tsc - old_sut_tsc + if pps_sut_tx_str <> 'NO_RESULTS': + log.info('|{:>4}'.format(size+4)+" |" + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps|'+' |' +' |' +' |'+ ' |'+ '{:>8.0f}'.format(lat_avg)+' us |'+'{:>8.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | '+ '{:>9.0f}'.format(rx) + ' | '+ '{:>7.0f}'.format(tx-rx) + ' | '+ '{:>7.0f}'.format(tot_drop) +' |'+lat_warning) + log.info("+-----+------------------+-------------+-------------+-------------+-------------+-------------+-------------+-----------+-----------+---------+------------+") + gensock.stop(latcores) + + def run_irqtest(sock): log.info("+----------------------------------------------------------------------------------------------------------------------------") @@ -606,72 +669,83 @@ def run_irqtest(sock): irq[i][j] = '0' else: irq[i][j] = str(round(diff/float(runtime), 2)) - log.info('\n'.join([''.join(['{:>12}'.format(item) for item in row]) for row in irq])) + for row in irq: + log.info(''.join(['{:>12}'.format(item) for item in row])) +# log.info('\n'.join([''.join(['{:>12}'.format(item) for item in row]) for row in irq])) def run_impairtest(gensock,sutsock): + size=PACKETSIZE-4 log.info("+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+") - log.info("| Generator is sending UDP (1 flow) packets (64 bytes) to SUT via GW dropping and delaying packets. SUT sends packets back. Use ctrl-c to stop the test |") + log.info("| Generator is sending UDP (1 flow) packets ("+ '{:>5}'.format(size+4) +" bytes) to SUT via GW dropping and delaying packets. SUT sends packets back. Use ctrl-c to stop the test |") log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+") log.info("| Test | Speed requested | Sent to NIC | Sent by Gen | Forward by SUT | Rec. by Gen | Avg. Latency | Max. Latency | Packets Lost | Loss Ratio |") log.info("+--------+--------------------+----------------+----------------+----------------+----------------+----------------+----------------+----------------+------------+") - size=60 attempts = 0 gensock.set_size(gencores,0,size) # This is setting the frame size gensock.set_value(gencores,0,16,(size-14),2) # 18 is the difference between the frame size and IP size = size of (MAC addresses, ethertype and FCS) gensock.set_value(gencores,0,38,(size-34),2) # 38 is the difference between the frame size and UDP size = 18 + size of IP header (=20) # This will only work when using sending UDP packets. For different protocols and ethernet types, we would need a different calculation + gensock.start(latcores) speed = STARTSPEED - gensock.speed(speed, gencores) + gensock.speed(speed / len(gencores), gencores) while True: attempts += 1 print('Measurement ongoing at speed: ' + str(round(speed,2)) + '% ',end='\r') sys.stdout.flush() time.sleep(1) # Get statistics now that the generation is stable and NO ARP messages any more - pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx = run_iteration(gensock,sutsock) + pps_req_tx,pps_tx,pps_sut_tx_str,pps_rx,lat_avg,lat_max, abs_dropped, abs_tx, lat_min, lat_used = run_iteration(gensock,sutsock) drop_rate = 100.0*abs_dropped/abs_tx - log.info('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(pps_tx) +' Mpps | ' + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+ '{:>9.0f}'.format(lat_avg)+' us | '+ '{:>9.0f}'.format(lat_max)+' us | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% |') + if lat_used < 0.95: + lat_warning = bcolors.FAIL + ' Potential latency accuracy problem: {:>3.0f}%'.format(lat_used*100) + bcolors.ENDC + else: + lat_warning = '' + log.info('|{:>7}'.format(str(attempts))+" | " + '{:>5.1f}'.format(speed) + '% ' +'{:>6.3f}'.format(get_pps(speed,size)) + ' Mpps | '+ '{:>9.3f}'.format(pps_req_tx)+' Mpps | '+ '{:>9.3f}'.format(pps_tx) +' Mpps | ' + '{:>9}'.format(pps_sut_tx_str) +' Mpps | '+ '{:>9.3f}'.format(pps_rx)+' Mpps | '+ '{:>9.0f}'.format(lat_avg)+' us | '+ '{:>9.0f}'.format(lat_max)+' us | '+ '{:>14d}'.format(abs_dropped)+ ' |''{:>9.2f}'.format(drop_rate)+ '% |'+lat_warning) + writer.writerow({'flow':'1','size':(size+4),'endspeed':speed,'endspeedpps':get_pps(speed,size),'endpps_req_tx':pps_req_tx,'endpps_tx':pps_tx,'endpps_sut_tx_str':pps_sut_tx_str,'endpps_rx':pps_rx,'endlat_avg':lat_avg,'endlat_max':lat_max,'endabs_dropped':abs_dropped,'enddrop_rate':drop_rate}) + gensock.stop(latcores) -def init_test(): +def run_inittest(gensock): # Running at low speed to make sure the ARP messages can get through. # If not doing this, the ARP message could be dropped by a switch in overload and then the test will not give proper results # Note hoever that if we would run the test steps during a very long time, the ARP would expire in the switch. # PROX will send a new ARP request every seconds so chances are very low that they will all fail to get through - socks[0].speed(0.01, gencores) - socks[0].start(genstatcores) + gensock.speed(0.01 / len(gencores), gencores) + gensock.start(genstatcores) time.sleep(2) - socks[0].stop(gencores) + gensock.stop(genstatcores) global sutstatcores global genstatcores global latcores global gencores global irqcores -global DROP_RATE_TRESHOLD -global LAT_AVG_TRESHOLD -global LAT_MAX_TRESHOLD -global ACCURACY -global STARTSPEED +global PACKETSIZE +global packet_size_list +global flow_size_list global required_number_of_test_machines clients =[] socks =[] +socks_control =[] vmDPIP =[] vmAdminIP =[] vmDPmac =[] hexDPIP =[] config_file =[] -script_control =[] +prox_socket =[] +prox_launch_exit =[] +auto_start =[] +mach_type =[] +sock_type =[] +data_file = 'RUN{}.{}.csv'.format(env,test) +data_csv_file = open(data_file,'w') testconfig = ConfigParser.RawConfigParser() testconfig.read(test+'.test') required_number_of_test_machines = testconfig.get('DEFAULT', 'total_number_of_test_machines') -DROP_RATE_TRESHOLD = float(testconfig.get('DEFAULT', 'drop_rate_treshold')) -LAT_AVG_TRESHOLD = float(testconfig.get('DEFAULT', 'lat_avg_treshold')) -LAT_MAX_TRESHOLD = float(testconfig.get('DEFAULT', 'lat_max_treshold')) -ACCURACY = float(testconfig.get('DEFAULT', 'accuracy')) -STARTSPEED = float(testconfig.get('DEFAULT', 'startspeed')) config = ConfigParser.RawConfigParser() config.read(env+'.env') +machine_map = ConfigParser.RawConfigParser() +machine_map.read(machine_map_file +'.cfg') key = config.get('OpenStack', 'key') total_number_of_machines = config.get('rapid', 'total_number_of_machines') if int(required_number_of_test_machines) > int(total_number_of_machines): @@ -685,108 +759,169 @@ for vm in range(1, int(total_number_of_machines)+1): hexDPIP.append(hex(int(ip[0]))[2:].zfill(2) + ' ' + hex(int(ip[1]))[2:].zfill(2) + ' ' + hex(int(ip[2]))[2:].zfill(2) + ' ' + hex(int(ip[3]))[2:].zfill(2)) machine_index = [] for vm in range(1, int(required_number_of_test_machines)+1): - machine_index.append(int(testconfig.get('TestM%d'%vm, 'machine_index'))-1) + machine_index.append(int(machine_map.get('TestM%d'%vm, 'machine_index'))-1) + prox_socket.append(testconfig.getboolean('TestM%d'%vm, 'prox_socket')) for vm in range(1, int(required_number_of_test_machines)+1): - config_file.append(testconfig.get('TestM%d'%vm, 'config_file')) - script_control.append(testconfig.get('TestM%d'%vm, 'script_control')) - group1cores=testconfig.get('TestM%d'%vm, 'group1cores') - if group1cores <> 'not_used': - group1cores=ast.literal_eval(group1cores) - group2cores=testconfig.get('TestM%d'%vm, 'group2cores') - if group2cores <> 'not_used': - group2cores=ast.literal_eval(group2cores) - group3cores=testconfig.get('TestM%d'%vm, 'group3cores') - if group3cores <> 'not_used': - group3cores=ast.literal_eval(group3cores) - with open("parameters%d.lua"%vm, "w") as f: - f.write('name="%s"\n'% testconfig.get('TestM%d'%vm, 'name')) - f.write('local_ip="%s"\n'% vmDPIP[machine_index[vm-1]]) - f.write('local_hex_ip="%s"\n'% hexDPIP[machine_index[vm-1]]) - gwVM = testconfig.get('TestM%d'%vm, 'gw_vm') - if gwVM <> 'not_used': - gwVMindex = int(gwVM)-1 - f.write('gw_ip="%s"\n'% vmDPIP[machine_index[gwVMindex]]) - f.write('gw_hex_ip="%s"\n'% hexDPIP[machine_index[gwVMindex]]) - destVM = testconfig.get('TestM%d'%vm, 'dest_vm') - if destVM <> 'not_used': - destVMindex = int(destVM)-1 - f.write('dest_ip="%s"\n'% vmDPIP[machine_index[destVMindex]]) - f.write('dest_hex_ip="%s"\n'% hexDPIP[machine_index[destVMindex]]) - f.write('dest_hex_mac="%s"\n'% vmDPmac[machine_index[destVMindex]].replace(':',' ')) - if group1cores <> 'not_used': - f.write('group1="%s"\n'% ','.join(map(str, group1cores))) - if group2cores <> 'not_used': - f.write('group2="%s"\n'% ','.join(map(str, group2cores))) - if group3cores <> 'not_used': - f.write('group3="%s"\n'% ','.join(map(str, group3cores))) - if re.match('(l2){0,1}gen.*\.cfg',config_file[-1]): - gencores = group1cores - latcores = group2cores - genstatcores = group3cores - elif config_file[-1] == 'gen_gw.cfg': - gencores = group1cores - latcores = group2cores - genstatcores = group3cores - elif re.match('(l2){0,1}swap.*\.cfg',config_file[-1]): - sutstatcores = group1cores - elif config_file[-1] == 'secgw2.cfg': - sutstatcores = group1cores - elif config_file[-1] == 'irq.cfg': - irqcores = group1cores - f.close + if prox_socket[vm-1]: + prox_launch_exit.append(testconfig.getboolean('TestM%d'%vm, 'prox_launch_exit')) + config_file.append(testconfig.get('TestM%d'%vm, 'config_file')) + with open('{}_{}_parameters{}.lua'.format(env,test,vm), "w") as f: + f.write('name="%s"\n'% testconfig.get('TestM%d'%vm, 'name')) + f.write('local_ip="%s"\n'% vmDPIP[machine_index[vm-1]]) + f.write('local_hex_ip="%s"\n'% hexDPIP[machine_index[vm-1]]) + if re.match('(l2){0,1}gen\.cfg',config_file[-1]): + gencores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'gencores')) + latcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'latcores')) + STARTSPEED = float(testconfig.get('TestM%d'%vm, 'startspeed')) + genstatcores = gencores + latcores + auto_start.append(False) + mach_type.append('gen') + f.write('gencores="%s"\n'% ','.join(map(str, gencores))) + f.write('latcores="%s"\n'% ','.join(map(str, latcores))) + destVMindex = int(testconfig.get('TestM%d'%vm, 'dest_vm'))-1 + f.write('dest_ip="%s"\n'% vmDPIP[machine_index[destVMindex]]) + f.write('dest_hex_ip="%s"\n'% hexDPIP[machine_index[destVMindex]]) + f.write('dest_hex_mac="%s"\n'% vmDPmac[machine_index[destVMindex]].replace(':',' ')) + elif re.match('(l2){0,1}gen_gw\.cfg',config_file[-1]): + gencores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'gencores')) + latcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'latcores')) + STARTSPEED = float(testconfig.get('TestM%d'%vm, 'startspeed')) + genstatcores = gencores + latcores + auto_start.append(False) + mach_type.append('gen') + f.write('gencores="%s"\n'% ','.join(map(str, gencores))) + f.write('latcores="%s"\n'% ','.join(map(str, latcores))) + gwVMindex = int(testconfig.get('TestM%d'%vm, 'gw_vm')) -1 + f.write('gw_ip="%s"\n'% vmDPIP[machine_index[gwVMindex]]) + f.write('gw_hex_ip="%s"\n'% hexDPIP[machine_index[gwVMindex]]) + destVMindex = int(testconfig.get('TestM%d'%vm, 'dest_vm'))-1 + f.write('dest_ip="%s"\n'% vmDPIP[machine_index[destVMindex]]) + f.write('dest_hex_ip="%s"\n'% hexDPIP[machine_index[destVMindex]]) + f.write('dest_hex_mac="%s"\n'% vmDPmac[machine_index[destVMindex]].replace(':',' ')) + elif re.match('(l2){0,1}swap.*\.cfg',config_file[-1]): + sutstatcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'swapcores')) + auto_start.append(True) + mach_type.append('sut') + f.write('swapcores="%s"\n'% ','.join(map(str, sutstatcores))) + elif config_file[-1] == 'secgw1.cfg': + auto_start.append(True) + mach_type.append('none') + f.write('secgwcores="%s"\n'% ','.join(map(str, ast.literal_eval(testconfig.get('TestM%d'%vm, 'secgwcores'))))) + destVMindex = int(testconfig.get('TestM%d'%vm, 'dest_vm'))-1 + f.write('dest_ip="%s"\n'% vmDPIP[machine_index[destVMindex]]) + f.write('dest_hex_ip="%s"\n'% hexDPIP[machine_index[destVMindex]]) + f.write('dest_hex_mac="%s"\n'% vmDPmac[machine_index[destVMindex]].replace(':',' ')) + elif config_file[-1] == 'secgw2.cfg': + sutstatcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'secgwcores')) + auto_start.append(True) + mach_type.append('sut') + f.write('secgwcores="%s"\n'% ','.join(map(str, sutstatcores))) + elif config_file[-1] == 'impair.cfg': + auto_start.append(True) + mach_type.append('none') + f.write('impaircores="%s"\n'% ','.join(map(str, ast.literal_eval(testconfig.get('TestM%d'%vm, 'impaircores'))))) + elif config_file[-1] == 'irq.cfg': + irqcores = ast.literal_eval(testconfig.get('TestM%d'%vm, 'irqcores')) + auto_start.append(False) + mach_type.append('irq') + f.write('irqcores="%s"\n'% ','.join(map(str, irqcores))) + f.close ##################################################################################### def exit_handler(): log.debug ('exit cleanup') - for sock in socks: - sock.quit() + for index, sock in enumerate(socks): + if socks_control[index]: + sock.quit() for client in clients: client.close() + data_csv_file.close sys.exit(0) atexit.register(exit_handler) for vm in range(0, int(required_number_of_test_machines)): - clients.append(prox_ctrl(vmAdminIP[machine_index[vm]], key+'.pem','root')) - connect_client(clients[-1]) + if prox_socket[vm]: + clients.append(prox_ctrl(vmAdminIP[machine_index[vm]], key+'.pem','root')) + connect_client(clients[-1]) # Creating script to bind the right network interface to the poll mode driver - devbindfile = "devbindvm%d.sh"%(vm+1) - with open("devbind.sh") as f: - newText=f.read().replace('MACADDRESS', vmDPmac[machine_index[vm]]) - with open(devbindfile, "w") as f: - f.write(newText) - st = os.stat(devbindfile) - os.chmod(devbindfile, st.st_mode | stat.S_IEXEC) - clients[-1].scp_put('./%s'%devbindfile, '/root/devbind.sh') - cmd = '/root/devbind.sh' - clients[-1].run_cmd(cmd) - log.debug("devbind.sh running on VM%d"%(vm+1)) - clients[-1].scp_put('./%s'%config_file[vm], '/root/%s'%config_file[vm]) - clients[-1].scp_put('./parameters%d.lua'%(vm+1), '/root/parameters.lua') - log.debug("Starting PROX on VM%d"%(vm+1)) - if script_control[vm] == 'true': - cmd = '/root/prox/build/prox -e -t -o cli -f /root/%s'%config_file[vm] - else: - cmd = '/root/prox/build/prox -t -o cli -f /root/%s'%config_file[vm] - if configonly == False: - clients[-1].fork_cmd(cmd, 'PROX Testing on TestM%d'%(vm+1)) - socks.append(connect_socket(clients[-1])) + devbindfile = '{}_{}_devbindvm{}.sh'.format(env,test, vm+1) + with open("devbind.sh") as f: + newText=f.read().replace('MACADDRESS', vmDPmac[machine_index[vm]]) + with open(devbindfile, "w") as f: + f.write(newText) + st = os.stat(devbindfile) + os.chmod(devbindfile, st.st_mode | stat.S_IEXEC) + clients[-1].scp_put('./%s'%devbindfile, '/root/devbind.sh') + cmd = '/root/devbind.sh' + clients[-1].run_cmd(cmd) + log.debug("devbind.sh running on VM%d"%(vm+1)) + clients[-1].scp_put('./%s'%config_file[vm], '/root/%s'%config_file[vm]) + clients[-1].scp_put('./{}_{}_parameters{}.lua'.format(env,test, vm+1), '/root/parameters.lua') + if not configonly: + if prox_launch_exit[vm]: + log.debug("Starting PROX on VM%d"%(vm+1)) + if auto_start[vm]: + cmd = '/root/prox/build/prox -t -o cli -f /root/%s'%config_file[vm] + else: + cmd = '/root/prox/build/prox -e -t -o cli -f /root/%s'%config_file[vm] + clients[-1].fork_cmd(cmd, 'PROX Testing on TestM%d'%(vm+1)) + socks_control.append(prox_launch_exit[vm]) + socks.append(connect_socket(clients[-1])) + sock_type.append(mach_type[vm]) +socks.append('none') +socks_control.append(False) + +def get_BinarySearchParams() : + global DROP_RATE_TRESHOLD + global LAT_AVG_TRESHOLD + global LAT_MAX_TRESHOLD + global ACCURACY + global STARTSPEED + DROP_RATE_TRESHOLD = float(testconfig.get('BinarySearchParams', 'drop_rate_threshold')) + LAT_AVG_TRESHOLD = float(testconfig.get('BinarySearchParams', 'lat_avg_threshold')) + LAT_MAX_TRESHOLD = float(testconfig.get('BinarySearchParams', 'lat_max_threshold')) + ACCURACY = float(testconfig.get('BinarySearchParams', 'accuracy')) + if configonly: sys.exit() -init_code = testconfig.get('DEFAULT', 'init_code') -if init_code <> 'not_used': - eval(init_code) #################################################### # Run test cases # Best to run the flow test at the end since otherwise the tests coming after might be influenced by the big number of entries in the switch flow tables #################################################### +gensock_index = sock_type.index('gen') if 'gen' in sock_type else -1 +sutsock_index = sock_type.index('sut') if 'sut' in sock_type else -1 +irqsock_index = sock_type.index('irq') if 'irq' in sock_type else -1 number_of_tests = testconfig.get('DEFAULT', 'number_of_tests') -data_file = 'RUN' +env+'.'+test+'.csv' -data_csv_file = open(data_file,'w') with data_csv_file: fieldnames = ['flow','size','endspeed','endspeedpps','endpps_req_tx','endpps_tx','endpps_sut_tx_str','endpps_rx','endlat_avg','endlat_max','endabs_dropped','enddrop_rate'] writer = csv.DictWriter(data_csv_file, fieldnames=fieldnames) writer.writeheader() - for vm in range(1, int(number_of_tests)+1): - cmd=testconfig.get('test%d'%vm,'cmd') - eval(cmd) + for test_nr in range(1, int(number_of_tests)+1): + test=testconfig.get('test%d'%test_nr,'test') + log.info(test) + if test == 'speedtest': + get_BinarySearchParams() + PACKETSIZE = int(testconfig.get('test%d'%test_nr, 'packetsize')) + run_speedtest(socks[gensock_index],socks[sutsock_index]) + elif test == 'flowtest': + get_BinarySearchParams() + PACKETSIZE = int(testconfig.get('test%d'%test_nr, 'packetsize')) + flow_size_list = ast.literal_eval(testconfig.get('test%d'%test_nr, 'flows')) + run_flowtest(socks[gensock_index],socks[sutsock_index]) + elif test == 'sizetest': + get_BinarySearchParams() + packet_size_list = ast.literal_eval(testconfig.get('test%d'%test_nr, 'packetsizes')) + run_sizetest(socks[gensock_index],socks[sutsock_index]) + elif test == 'max_frame_rate': +# PACKETSIZE = int(testconfig.get('test%d'%test_nr, 'packetsize')) + packet_size_list = ast.literal_eval(testconfig.get('test%d'%test_nr, 'packetsizes')) + run_max_frame_rate(socks[gensock_index],socks[sutsock_index]) + elif test == 'impairtest': + get_BinarySearchParams() + PACKETSIZE = int(testconfig.get('test%d'%test_nr, 'packetsize')) + run_impairtest(socks[gensock_index],socks[sutsock_index]) + elif test == 'irqtest': + run_irqtest(socks[irqsock_index]) + elif test == 'inittest': + run_inittest(socks[gensock_index]) #################################################### diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw.test b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw.test index 7cfa7e6d..cf1b5522 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw.test +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw.test @@ -16,44 +16,40 @@ [DEFAULT] name = GWTesting -number_of_tests = 1 +number_of_tests = 2 total_number_of_test_machines = 3 -init_code=init_test() -dest_vm = not_used -gw_vm = not_used -script_control = false -group1cores = not_used -group2cores = not_used -group3cores = not_used -drop_rate_treshold = 0.01 -lat_avg_treshold = 200 -lat_max_treshold = 1000 -accuracy = 0.01 -startspeed = 10 +prox_socket = true +prox_launch_exit = true [TestM1] name = Generator -machine_index = 1 config_file = gen_gw.cfg dest_vm = 3 gw_vm = 2 -script_control = true -group1cores = [1] -group2cores = [3] -group3cores = [1,3] +gencores = [1] +latcores = [3] +startspeed = 10 [TestM2] name = GW1 -machine_index = 2 config_file = secgw1.cfg dest_vm = 3 -group1cores = [1] +secgwcores = [1] [TestM3] name = GW2 -machine_index = 3 config_file = secgw2.cfg -group1cores = [1] +secgwcores = [1] + +[BinarySearchParams] +drop_rate_threshold = 0.1 +lat_avg_threshold = 500 +lat_max_threshold = 1000 +accuracy = 0.1 [test1] -cmd=run_speedtest(socks[0],socks[2]) +test=inittest + +[test2] +test=speedtest +packetsize=64 diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw1.cfg b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw1.cfg index 7788b386..301a138e 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw1.cfg +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw1.cfg @@ -43,7 +43,7 @@ name=${name} [core 0] mode=master -[core $group1] +[core $secgwcores] name=esp_enc task=0 mode=esp_enc diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw2.cfg b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw2.cfg index dfaf253a..9c970e83 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw2.cfg +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/secgw2.cfg @@ -42,7 +42,7 @@ name=${name} [core 0] mode=master -[core $group1] +[core $secgwcores] name=esp_dec task=0 mode=esp_dec diff --git a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/swap.cfg b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/swap.cfg index 2f736b16..47cb0b07 100644 --- a/VNFs/DPPD-PROX/helper-scripts/openstackrapid/swap.cfg +++ b/VNFs/DPPD-PROX/helper-scripts/openstackrapid/swap.cfg @@ -34,7 +34,7 @@ name=${name} [core 0] mode=master -[core $group1] +[core $swapcores] name=swap task=0 mode=swap @@ -43,4 +43,4 @@ rx port=if0 tx port=if0 local ipv4=${local_ip} drop=no - +;arp update time=1 |