Merge "Add send socket commands function"
authorRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Tue, 10 Jul 2018 07:48:43 +0000 (07:48 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Tue, 10 Jul 2018 07:48:43 +0000 (07:48 +0000)
298 files changed:
ansible/install-inventory.ini [new file with mode: 0644]
ansible/install.yaml
ansible/install_trex_standalone.yml [deleted file]
ansible/roles/configure_nginx/tasks/main.yml
ansible/roles/configure_uwsgi/templates/yardstick.ini.j2
ansible/roles/download_dpdk/defaults/main.yml
ansible/roles/download_dpdk/tasks/main.yml
ansible/roles/download_samplevnfs/defaults/main.yml
ansible/roles/install_samplevnf/vars/main.yml
ansible/roles/install_yardstick/tasks/main.yml
ansible/roles/install_yardstick/tasks/regular_install.yml [deleted file]
ansible/roles/install_yardstick/tasks/virtual_install.yml [deleted file]
ansible/ubuntu_server_baremetal_deploy_samplevnfs.yml
ansible/ubuntu_server_cloudimg_modify_samplevnfs.yml
ansible/yardstick-install-inventory.ini [deleted file]
dashboard/Prox_BM_L3FWD-4Port-1529606919144.json [new file with mode: 0644]
dashboard/Prox_BM_vPE-4Port-1507804058631.json [deleted file]
dashboard/Prox_BM_vpe-4Port-1529345833067.json [moved from dashboard/Prox_BM_L3FWD-4Port-1527840729877.json with 90% similarity]
docker/Dockerfile
docker/Dockerfile.aarch64.patch
docs/release/release-notes/release-notes.rst
docs/release/results/euphrates_fraser_comparison.rst [new file with mode: 0644]
docs/release/results/euphrates_fraser_comparsion.rst [deleted file]
docs/release/results/images/tc002_pod_fraser.png [new file with mode: 0644]
docs/release/results/images/tc002_scenario_fraser.png [new file with mode: 0644]
docs/release/results/images/tc010_pod_fraser.png [new file with mode: 0644]
docs/release/results/images/tc010_scenario_fraser.png [new file with mode: 0644]
docs/release/results/images/tc011_pod_fraser.png [new file with mode: 0644]
docs/release/results/images/tc011_scenario_fraser.png [new file with mode: 0644]
docs/release/results/images/tc012_pod_fraser.png [new file with mode: 0644]
docs/release/results/images/tc012_scenario_fraser.png [new file with mode: 0644]
docs/release/results/images/tc014_pod_fraseer.png [new file with mode: 0644]
docs/release/results/images/tc014_scenario_fraser.png [new file with mode: 0644]
docs/release/results/images/tc069_pod_fraser.png [new file with mode: 0644]
docs/release/results/images/tc069_scenario_fraser.png [new file with mode: 0644]
docs/release/results/images/tc082_pod_fraser.png [new file with mode: 0644]
docs/release/results/images/tc083_pod_fraser.png [new file with mode: 0644]
docs/release/results/index.rst
docs/release/results/results.rst
docs/release/results/tc002-network-latency.rst
docs/release/results/tc010-memory-read-latency.rst
docs/release/results/tc011-packet-delay-variation.rst
docs/release/results/tc012-memory-read-write-bandwidth.rst
docs/release/results/tc014-cpu-processing-speed.rst
docs/release/results/tc069-memory-write-bandwidth.rst
docs/release/results/tc082-context-switches-under-load.rst
docs/release/results/tc083-network-throughput-between-vm.rst
docs/testing/developer/devguide/devguide.rst
docs/testing/developer/devguide/devguide_nsb_prox.rst
docs/testing/developer/devguide/images/PROX_Grafana_1.png [new file with mode: 0644]
docs/testing/developer/devguide/images/PROX_Grafana_2.png [new file with mode: 0644]
docs/testing/developer/devguide/images/PROX_Grafana_3.png [new file with mode: 0644]
docs/testing/developer/devguide/images/PROX_Grafana_4.png [new file with mode: 0644]
docs/testing/developer/devguide/images/PROX_Test_BM_Script.png
docs/testing/developer/devguide/images/PROX_Test_HEAT_Script.png [deleted file]
docs/testing/developer/devguide/images/PROX_Test_HEAT_Script1.png [new file with mode: 0644]
docs/testing/developer/devguide/images/PROX_Test_HEAT_Script2.png [new file with mode: 0644]
docs/testing/developer/devguide/index.rst
docs/testing/user/userguide/14-nsb-operation.rst
nsb_setup.sh
requirements.txt
samples/vnf_samples/nsut/acl/acl_1rule.yaml
samples/vnf_samples/nsut/acl/acl_rules.yaml
samples/vnf_samples/nsut/acl/acl_worstcaserules.yaml
samples/vnf_samples/nsut/acl/tc_ovs_rfc2544_ipv4_1rule_1flow_64B_trex.yaml
samples/vnf_samples/nsut/prox/configs/gen_bng-4.cfg
samples/vnf_samples/nsut/prox/configs/gen_bng_qos-4.cfg
samples/vnf_samples/nsut/prox/configs/handle_bng-4.cfg
samples/vnf_samples/nsut/prox/configs/handle_bng_qos-4.cfg
samples/vnf_samples/nsut/prox/prox-tg-topology-4.yaml
samples/vnf_samples/nsut/prox/prox-tg-topology-scale-out.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/prox/tc_prox_baremetal_bng-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_baremetal_bng_qos-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_baremetal_l2fwd-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_baremetal_vpe-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_acl-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_acl-scale-up.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_bng-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_bng_qos-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_l2fwd-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_l2fwd_multiflow-2-scale-out.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/prox/tc_prox_heat_context_l2fwd_multiflow-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_l2fwd_pktTouch-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_l3fwd-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_l3fwd-scale-up.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_lb-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_mpls_tagging-4.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_mpls_tagging-scale-up.yaml
samples/vnf_samples/nsut/prox/tc_prox_heat_context_vpe-4.yaml
samples/vnf_samples/nsut/vfw/acl_1rule.yaml
samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_64B_trex_iterationipc.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_64B_trex_scale_out.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/vfw/vfw_tg_topology_scale_out.yaml [new file with mode: 0644]
samples/vnf_samples/traffic_profiles/ipv4_throughput-10.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput-2.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput-3.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput-4.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput-cgnapt-ixia-scale-out.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput-cgnapt-scale-out.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput-ixia-correlated-scale-out.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput-ixia-scale-out.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput-scale-out.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput-scale-up.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput_cgnapt-10.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput_cgnapt-2.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput_cgnapt-4.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput_cgnapt-scale-out.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput_cgnapt.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput_scale_out.yaml [new file with mode: 0644]
samples/vnf_samples/traffic_profiles/ipv4_throughput_vpe.yaml
samples/vnf_samples/traffic_profiles/ixia_ipv4_latency.yaml
samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_cgnapt.yaml
samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vpe.yaml
samples/vnf_samples/traffic_profiles/prox_bng.yaml
samples/vnf_samples/traffic_profiles/prox_vpe.yaml
test-requirements.txt
tests/opnfv/test_cases/opnfv_yardstick_tc001.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc002.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc005.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc006.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc008.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc009.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc010.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc011.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc012.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc014.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc023.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc038.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc069.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc070.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc071.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc072.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc076.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc079.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc082.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc083.yaml
tests/opnfv/test_cases/opnfv_yardstick_tc084.yaml
tests/opnfv/test_suites/opnfv_os-odl-ovs-noha_daily.yaml [new file with mode: 0644]
tests/unit/__init__.py [deleted file]
tests/unit/network_services/__init__.py [deleted file]
tools/cover.sh
tools/run_tests.sh
yardstick/benchmark/contexts/base.py
yardstick/benchmark/contexts/dummy.py
yardstick/benchmark/contexts/heat.py
yardstick/benchmark/contexts/kubernetes.py
yardstick/benchmark/contexts/node.py
yardstick/benchmark/contexts/standalone/model.py
yardstick/benchmark/contexts/standalone/ovs_dpdk.py
yardstick/benchmark/contexts/standalone/sriov.py
yardstick/benchmark/core/task.py
yardstick/benchmark/runners/arithmetic.py
yardstick/benchmark/runners/base.py
yardstick/benchmark/runners/duration.py
yardstick/benchmark/runners/dynamictp.py
yardstick/benchmark/runners/iteration.py
yardstick/benchmark/runners/iteration_ipc.py [new file with mode: 0644]
yardstick/benchmark/runners/proxduration.py [new file with mode: 0644]
yardstick/benchmark/runners/search.py
yardstick/benchmark/runners/sequence.py
yardstick/benchmark/scenarios/availability/scenario_general.py
yardstick/benchmark/scenarios/availability/serviceha.py
yardstick/benchmark/scenarios/base.py
yardstick/benchmark/scenarios/compute/cyclictest.py
yardstick/benchmark/scenarios/compute/lmbench.py
yardstick/benchmark/scenarios/compute/perf.py
yardstick/benchmark/scenarios/compute/qemu_migrate.py
yardstick/benchmark/scenarios/compute/ramspeed.py
yardstick/benchmark/scenarios/compute/unixbench.py
yardstick/benchmark/scenarios/networking/iperf3.py
yardstick/benchmark/scenarios/networking/moongen_testpmd.py
yardstick/benchmark/scenarios/networking/netperf.py
yardstick/benchmark/scenarios/networking/netperf_node.py
yardstick/benchmark/scenarios/networking/nstat.py
yardstick/benchmark/scenarios/networking/ping.py
yardstick/benchmark/scenarios/networking/ping6.py
yardstick/benchmark/scenarios/networking/pktgen.py
yardstick/benchmark/scenarios/networking/pktgen_dpdk.py
yardstick/benchmark/scenarios/networking/pktgen_dpdk_throughput.py
yardstick/benchmark/scenarios/networking/vnf_generic.py
yardstick/benchmark/scenarios/networking/vsperf.py
yardstick/benchmark/scenarios/networking/vsperf_dpdk.py
yardstick/benchmark/scenarios/storage/fio.py
yardstick/common/constants.py
yardstick/common/exceptions.py
yardstick/common/messaging/__init__.py
yardstick/common/messaging/consumer.py
yardstick/common/messaging/payloads.py
yardstick/common/messaging/producer.py
yardstick/common/openstack_utils.py
yardstick/common/utils.py
yardstick/common/yaml_loader.py
yardstick/network_services/collector/subscriber.py
yardstick/network_services/helpers/samplevnf_helper.py
yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
yardstick/network_services/nfvi/resource.py
yardstick/network_services/traffic_profile/base.py
yardstick/network_services/traffic_profile/ixia_rfc2544.py
yardstick/network_services/traffic_profile/prox_binsearch.py
yardstick/network_services/traffic_profile/rfc2544.py
yardstick/network_services/traffic_profile/trex_traffic_profile.py
yardstick/network_services/vnf_generic/vnf/acl_vnf.py
yardstick/network_services/vnf_generic/vnf/base.py
yardstick/network_services/vnf_generic/vnf/prox_helpers.py
yardstick/network_services/vnf_generic/vnf/prox_vnf.py
yardstick/network_services/vnf_generic/vnf/router_vnf.py
yardstick/network_services/vnf_generic/vnf/sample_vnf.py
yardstick/network_services/vnf_generic/vnf/tg_ixload.py
yardstick/network_services/vnf_generic/vnf/tg_ping.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
yardstick/network_services/vnf_generic/vnf/tg_trex.py
yardstick/network_services/vnf_generic/vnf/udp_replay.py
yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
yardstick/network_services/vnf_generic/vnf/vnf_ssh_helper.py
yardstick/network_services/vnf_generic/vnf/vpe_vnf.py
yardstick/network_services/yang_model.py [deleted file]
yardstick/orchestrator/kubernetes.py
yardstick/ssh.py
yardstick/tests/functional/common/messaging/test_messaging.py
yardstick/tests/unit/apiserver/utils/test_influx.py
yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py
yardstick/tests/unit/benchmark/contexts/test_base.py
yardstick/tests/unit/benchmark/contexts/test_dummy.py
yardstick/tests/unit/benchmark/contexts/test_heat.py
yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
yardstick/tests/unit/benchmark/contexts/test_node.py
yardstick/tests/unit/benchmark/core/test_plugin.py
yardstick/tests/unit/benchmark/core/test_report.py
yardstick/tests/unit/benchmark/core/test_task.py
yardstick/tests/unit/benchmark/runner/test_base.py
yardstick/tests/unit/benchmark/runner/test_duration.py [new file with mode: 0644]
yardstick/tests/unit/benchmark/runner/test_iteration_ipc.py [new file with mode: 0644]
yardstick/tests/unit/benchmark/runner/test_proxduration.py [new file with mode: 0644]
yardstick/tests/unit/benchmark/runner/test_search.py
yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py
yardstick/tests/unit/benchmark/scenarios/availability/test_scenario_general.py
yardstick/tests/unit/benchmark/scenarios/availability/test_serviceha.py
yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py
yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py
yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py
yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py
yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py
yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py
yardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py
yardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py
yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py
yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py
yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py
yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py
yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py
yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py
yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py
yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py
yardstick/tests/unit/common/messaging/test_payloads.py
yardstick/tests/unit/common/messaging/test_producer.py
yardstick/tests/unit/common/test_openstack_utils.py
yardstick/tests/unit/common/test_process.py
yardstick/tests/unit/common/test_utils.py
yardstick/tests/unit/network_services/collector/test_subscriber.py
yardstick/tests/unit/network_services/helpers/test_dpdkbindnic_helper.py
yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py
yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py
yardstick/tests/unit/network_services/nfvi/test_resource.py
yardstick/tests/unit/network_services/test_yang_model.py [deleted file]
yardstick/tests/unit/network_services/traffic_profile/test_base.py
yardstick/tests/unit/network_services/traffic_profile/test_fixed.py
yardstick/tests/unit/network_services/traffic_profile/test_http.py
yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py
yardstick/tests/unit/network_services/traffic_profile/test_prox_binsearch.py
yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py
yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py
yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py
yardstick/tests/unit/network_services/vnf_generic/vnf/acl_1rule.yaml [deleted file]
yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_base.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_vnf.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_router_vnf.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ixload.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ping.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_udp_replay.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py
yardstick/tests/unit/orchestrator/test_kubernetes.py
yardstick/tests/unit/test_cmd/commands/test_env.py
yardstick/tests/unit/test_ssh.py

diff --git a/ansible/install-inventory.ini b/ansible/install-inventory.ini
new file mode 100644 (file)
index 0000000..6aa9905
--- /dev/null
@@ -0,0 +1,30 @@
+# the group of systems on which to install yardstick
+# by default just localhost
+[jumphost]
+#yardstickvm1 ansible_user=ubuntu ansible_ssh_pass=password ansible_connection=local
+localhost ansible_connection=local
+
+# section below is only due backward compatibility.
+# it will be removed later
+[yardstick:children]
+jumphost
+
+[yardstick-standalone]
+#yardstickvm2 ansible_host=192.168.2.51 ansible_user=ubuntu ansible_ssh_pass=password ansible_connection=ssh
+# uncomment hosts below if you would to test yardstick-standalone/sriov scenarios
+#yardstick-standalone-node ansible_host=192.168.1.2
+#yardstick-standalone-node-2 ansible_host=192.168.1.3
+
+[yardstick-baremetal]
+#yardstickvm3 ansible_host=192.168.2.52 ansible_user=ubuntu ansible_ssh_pass=password ansible_connection=ssh
+# hostname ansible_host=192.168.1.2
+
+[all:vars]
+arch_amd64=amd64
+arch_arm64=arm64
+inst_mode_container=container
+inst_mode_baremetal=baremetal
+ubuntu_archive={"amd64": "http://archive.ubuntu.com/ubuntu/", "arm64": "http://ports.ubuntu.com/ubuntu-ports/"}
+# uncomment credentials below for yardstick-standalone
+#ansible_user=root
+#ansible_pass=root
index c446b91..e93232d 100644 (file)
@@ -1,14 +1,20 @@
+# Copyright (c) 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.
 ---
-- hosts: localhost
-
+- hosts: jumphost
+  become: yes
   vars:
-    arch_amd64: "amd64"
-    arch_arm64: "arm64"
-    inst_mode_container: "container"
-    inst_mode_baremetal: "baremetal"
-    ubuntu_archive:
-      amd64: "http://archive.ubuntu.com/ubuntu/"
-      arm64: "http://ports.ubuntu.com/ubuntu-ports/"
     installation_mode: "{{ INSTALLATION_MODE | default('baremetal') }}"
     yardstick_dir: "{{ YARDSTICK_DIR | default('/home/opnfv/repos/yardstick') }}"
     virtual_environment: "{{ VIRTUAL_ENVIRONMENT | default(False) }}"
@@ -29,6 +35,7 @@
     - install_yardstick
     - configure_uwsgi
     - configure_nginx
+    - configure_gui
     - download_trex
     - install_trex
     - configure_rabbitmq
 
     - shell: uwsgi -i /etc/yardstick/yardstick.ini
       when: installation_mode != inst_mode_container
+
+- name: Prepare baremetal and standalone server(s)
+  hosts: yardstick-baremetal,yardstick-standalone
+  become: yes
+  vars:
+    YARD_IMG_ARCH: "{{ arch_amd64 }}"
+  environment:
+    proxy_env:
+      http_proxy: "{{ lookup('env', 'http_proxy') }}"
+      https_proxy: "{{ lookup('env', 'https_proxy') }}"
+      ftp_proxy: "{{ lookup('env', 'ftp_proxy') }}"
+      no_proxy: "{{ lookup('env', 'no_proxy') }}"
+
+  roles:
+    - add_custom_repos
+    - role: set_package_installer_proxy
+      when: proxy_env is defined and proxy_env
+    # can't update grub in chroot/docker
+    - enable_hugepages_on_boot
+    # needed for collectd plugins
+    - increase_open_file_limits
+    - install_image_dependencies
+    - role: download_dpdk
+    # dpdk_version: "17.02"
+    - install_dpdk
+    - download_trex
+    - install_trex
+    - download_civetweb
+    - install_civetweb
+    - download_samplevnfs
+    - role: install_samplevnf
+      vnf_name: PROX
+    - role: install_samplevnf
+      vnf_name: UDP_Replay
+    - role: install_samplevnf
+      vnf_name: ACL
+    - role: install_samplevnf
+      vnf_name: FW
+    - role: install_samplevnf
+      vnf_name: CGNATP
+    # build shared DPDK for collectd only, required DPDK downloaded already
+    - install_dpdk_shared
+    - install_rabbitmq
+    - download_intel_cmt_cat
+    - install_intel_cmt_cat
+    - download_pmu_tools
+    - install_pmu_tools
+    - download_collectd
+    - install_collectd
diff --git a/ansible/install_trex_standalone.yml b/ansible/install_trex_standalone.yml
deleted file mode 100644 (file)
index 9cf6414..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (c) 2017 Intel Corporation.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
----
-- hosts: yardstick
-  vars:
-    ansible_python_interpreter: "/usr/bin/env python"
-    # needed for virtualenv
-    NSB_INSTALL_DIR: /root/nsb_install
-    INSTALL_BIN_PATH: /opt/nsb_bin
-    #TREX_DOWNLOAD: "https://trex-tgn.cisco.com/trex/release/v2.05.tar.gz"
-    TREX_VERSION: v2.20
-    TREX_DOWNLOAD: "https://trex-tgn.cisco.com/trex/release/{{ TREX_VERSION }}.tar.gz"
-
-  tasks:
-    - get_url:
-        url: "{{ TREX_DOWNLOAD }}"
-        dest: "{{ NSB_INSTALL_DIR }}"
-        checksum: "sha256:b9620341e552d2ef71d5ffa39ef92f12a1186836c250390db77bd7228497b91c"
-
-    - unarchive:
-        src: "{{ NSB_INSTALL_DIR }}/{{ TREX_DOWNLOAD|basename }}"
-        dest: "{{ NSB_INSTALL_DIR }}"
-        copy: no
-
-    - file: path="{{ INSTALL_BIN_PATH }}/trex" state=absent
-    - file: path="{{ INSTALL_BIN_PATH }}/trex" state=directory
-
-    - command: mv "{{ NSB_INSTALL_DIR }}/{{ TREX_DOWNLOAD|basename|regex_replace('\.tar.gz', '') }}" "{{ INSTALL_BIN_PATH }}/trex/scripts"
-
-    - file: path="{{ INSTALL_BIN_PATH }}/trex/scripts/automation/trex_control_plane/stl/__init__.py" state=touch
-
-    - command: cp "{{ INSTALL_BIN_PATH }}/trex/scripts/dpdk_nic_bind.py" "{{ INSTALL_BIN_PATH }}"
-
-    - name: add scripts to PYTHONPATH
-      lineinfile:
-        dest: /etc/environment
-        regexp: "^PYTHONPATH="
-        line: "PYTHONPATH={{ INSTALL_BIN_PATH }}/trex/scripts/automation/trex_control_plane:{{ INSTALL_BIN_PATH }}/trex/scripts/automation/trex_control_plane/stl:{{ NSB_INSTALL_DIR }}/yardstick"
-        state: present
-        create: yes
index 37b0527..e0f7f75 100644 (file)
@@ -30,4 +30,4 @@
   shell: |
     semanage port -m -t http_port_t  -p tcp 5000
     semanage port -m -t http_port_t  -p udp 5000
-  when: ansible_os_family == "RedHat"
\ No newline at end of file
+  when: ansible_os_family == "RedHat"
index c049daf..044f42a 100644 (file)
@@ -1,7 +1,7 @@
 [uwsgi]
 master = true
 debug = true
-chdir = {{ yardstick_dir }}api
+chdir = {{ yardstick_dir }}/api
 module = server
 plugins = python
 processes = 10
@@ -15,4 +15,4 @@ close-on-exec = 1
 daemonize = {{ log_dir }}uwsgi.log
 socket = {{ socket_file }}
 {# If virtual environment, we need to add:
-   virtualenv = <virtual_env> #}
\ No newline at end of file
+   virtualenv = <virtual_env> #}
index d548280..885eebf 100644 (file)
@@ -1,14 +1,18 @@
 ---
-dpdk_version: "17.02"
-dpdk_url: "http://dpdk.org/browse/dpdk/snapshot/dpdk-{{ dpdk_version }}.tar.gz"
+dpdk_version: "17.02.1"
+dpdk_url: "http://fast.dpdk.org/rel/dpdk-{{ dpdk_version }}.tar.xz"
 dpdk_file: "{{ dpdk_url|basename }}"
-dpdk_unarchive: "{{ dpdk_file|regex_replace('[.]tar[.]gz$', '') }}"
+dpdk_unarchive: "{{ dpdk_file|regex_replace('[.]tar[.]xz$', '') }}"
 dpdk_dest: "{{ clone_dest }}/"
-#Note DPDK 17.08 17.11 and 18.02 are currently unsupported due to prox build issues
-dpdk_sha256s:
-  "16.07": "sha256:d876e4b2a7101f28e7e345d3c88e66afe877d15f0159c19c5bc5bc26b7b7d788"
-  "17.02": "sha256:b07b546e910095174bdb6152bb0d7ce057cc4b79aaa74771aeee4e8a7219fb38"
-  "17.05": "sha256:763bfb7e1765efcc949e79d645dc9f1ebd16591431ba0db5ce22becd928dcd0a"
-  "17.08": "sha256:3a08addbff45c636538514e9a5838fb91ea557661a4c071e03a9a6987d46e5b6" #unsupported
-  "17.11": "sha256:77a727bb3834549985f291409c9a77a1e8be1c9329ce4c3eb19a22d1461022e4" #unsupported
-  "18.02": "sha256:f1210310fd5f01a3babe3a09d9b3e5a9db791c2ec6ecfbf94ade9f893a0632b8" #unsupported
+
+#NOTE(ralonsoh): DPDK > 17.02 are currently unsupported due to prox build issues
+dpdk_md5:
+  "16.07.2": "md5:4922ea2ec935b64ff5c191fec53344a6"
+  "16.11.7": "md5:c081d113dfd57633e3bc3ebc802691be"
+  "17.02.1": "md5:cbdf8b7a92ce934d47c38cbc9c20c54a"
+  "17.05": "md5:0a68c31cd6a6cabeed0a4331073e4c05" #Ubuntu 17.10 support
+  "17.05.2": "md5:37afc9ce410d8e6945a1beb173074003" #unsupported
+  "17.08.2": "md5:dd239a878c8c40cf482fdfe438f8d99c" #unsupported
+  "17.11.3": "md5:68ca84ac878011acf44e75d33b46f55b" #unsupported
+  "18.02.2": "md5:75ad6d39b513649744e49c9fcbbb9ca5" #unsupported
+  "18.05": "md5:9fc86367cd9407ff6a8dfea56c4eddc4" #unsupported
index bcb5dde..bea3feb 100644 (file)
@@ -25,7 +25,7 @@
     url: "{{ dpdk_url }}"
     dest: "{{ dpdk_dest }}"
     validate_certs: False
-    checksum: "{{ dpdk_sha256s[dpdk_version] }}"
+    checksum: "{{ dpdk_md5[dpdk_version] }}"
 
 - unarchive:
     src: "{{ dpdk_dest }}/{{ dpdk_file }}"
index e40eb67..c5e880e 100644 (file)
@@ -1,4 +1,4 @@
 ---
 samplevnf_url: "https://git.opnfv.org/samplevnf"
 samplevnf_dest: "{{ clone_dest }}/samplevnf"
-samplevnf_version: "stable/euphrates"
+samplevnf_version: "stable/fraser"
index 45cea68..c92a9b0 100644 (file)
@@ -47,12 +47,14 @@ vnf_build_dependencies:
 vnf_build_dirs:
   ACL: vACL
   FW: vFW
-  CGNATP: vCGNAPT
+  CGNAPT: vCGNAPT
+  PE: vPE
   UDP_Replay: UDP_Replay
   PROX: DPPD-PROX
 vnf_app_names:
   ACL: vACL
   FW: vFW
-  CGNATP: vCGNAPT
+  CGNAPT: vCGNAPT
+  PE: vPE
   UDP_Replay: UDP_Replay
   PROX: prox
index ee1b837..973b2b0 100644 (file)
 #    name: pip
 #    state: latest
 
-- name: install yardstick without virtual environment
-  include_tasks: regular_install.yml
+- name: Install Yardstick requirements (venv)
+  pip:
+    requirements: "{{ yardstick_dir }}/requirements.txt"
+    virtualenv: "{{ yardstick_dir }}/virtualenv"
+  async: 300
+  poll: 0
+  register: pip_installer
+  when: virtual_environment == True
+
+- name: Install Yardstick requirements
+  pip:
+    requirements: "{{ yardstick_dir }}/requirements.txt"
+  async: 300
+  poll: 0
+  register: pip_installer
   when: virtual_environment == False
 
-- name: install yardstick with virtual environment
-  include_tasks: virtual_install.yml
+- name: Check install Yardstick requirements
+  async_status:
+    jid: "{{ pip_installer.ansible_job_id }}"
+  register: job_result
+  until: job_result.finished
+  retries: 100
+
+- name: Install Yardstick code (venv)
+  pip:
+    name: "{{ yardstick_dir }}/"
+    editable: True
+    virtualenv: "{{ yardstick_dir }}/virtualenv"
   when: virtual_environment == True
+
+- name: Install Yardstick code
+  pip:
+    name: "{{ yardstick_dir }}/"
+    editable: True
+  when: virtual_environment == False
diff --git a/ansible/roles/install_yardstick/tasks/regular_install.yml b/ansible/roles/install_yardstick/tasks/regular_install.yml
deleted file mode 100644 (file)
index 4a9925a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 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.
----
-- name: Install Yardstick requirements
-  pip:
-    requirements: "{{ yardstick_dir }}/requirements.txt"
-
-- name: Install Yardstick code
-  pip:
-    name: "{{ yardstick_dir }}/."
-    extra_args: -e
diff --git a/ansible/roles/install_yardstick/tasks/virtual_install.yml b/ansible/roles/install_yardstick/tasks/virtual_install.yml
deleted file mode 100644 (file)
index 8545acb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (c) 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.
----
-- name: Install Yardstick requirements
-  pip:
-    requirements: "{{ yardstick_dir }}/requirements.txt"
-    virtualenv: "{{ yardstick_dir }}/virtualenv"
-
-- name: Install Yardstick code
-  pip:
-    name: "{{ yardstick_dir }}/."
-    extra_args: -e
-    virtualenv: "{{ yardstick_dir }}/virtualenv"
-
index 479b45c..d858257 100644 (file)
@@ -44,7 +44,9 @@
     - role: install_samplevnf
       vnf_name: FW
     - role: install_samplevnf
-      vnf_name: CGNATP
+      vnf_name: CGNAPT
+    - role: install_samplevnf
+      vnf_name: PE
     # build shared DPDK for collectd only, required DPDK downloaded already
     - install_dpdk_shared
     - install_rabbitmq
index 7aa6c8c..aab5a74 100644 (file)
@@ -54,7 +54,9 @@
     - role: install_samplevnf
       vnf_name: FW
     - role: install_samplevnf
-      vnf_name: CGNATP
+      vnf_name: CGNAPT
+    - role: install_samplevnf
+      vnf_name: PE
     # build shared DPDK for collectd only, required DPDK downloaded already
     - install_dpdk_shared
     - install_rabbitmq
diff --git a/ansible/yardstick-install-inventory.ini b/ansible/yardstick-install-inventory.ini
deleted file mode 100644 (file)
index e276076..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# the group of systems on which to install yardstick
-# by default just localhost
-[jumphost]
-localhost  ansible_connection=local
-
-# section below is only due backward compatibility.
-# it will be removed later
-[yardstick:children]
-jumphost
-
-[yardstick-standalone]
-# uncomment hosts below if you would to test yardstick-standalone/sriov scenarios
-#yardstick-standalone-node ansible_host=192.168.1.2
-#yardstick-standalone-node-2 ansible_host=192.168.1.2
-
-[all:vars]
-# incomment credentials below for yardstick-standalone
-#ansible_user=root
-#ansible_pass=root
-
diff --git a/dashboard/Prox_BM_L3FWD-4Port-1529606919144.json b/dashboard/Prox_BM_L3FWD-4Port-1529606919144.json
new file mode 100644 (file)
index 0000000..6f6adcc
--- /dev/null
@@ -0,0 +1,12735 @@
+{
+  "__inputs": [
+    {
+      "name": "DS_YARDSTICK",
+      "label": "yardstick",
+      "description": "",
+      "type": "datasource",
+      "pluginId": "influxdb",
+      "pluginName": "InfluxDB"
+    }
+  ],
+  "__requires": [
+    {
+      "type": "grafana",
+      "id": "grafana",
+      "name": "Grafana",
+      "version": "5.2.0-beta2"
+    },
+    {
+      "type": "panel",
+      "id": "graph",
+      "name": "Graph",
+      "version": "5.0.0"
+    },
+    {
+      "type": "datasource",
+      "id": "influxdb",
+      "name": "InfluxDB",
+      "version": "5.0.0"
+    },
+    {
+      "type": "panel",
+      "id": "singlestat",
+      "name": "Singlestat",
+      "version": "5.0.0"
+    },
+    {
+      "type": "panel",
+      "id": "text",
+      "name": "Text",
+      "version": "5.0.0"
+    }
+  ],
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "id": null,
+  "links": [],
+  "panels": [
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 32px '#31A7D3'\"><center>OPNFV_Yardstick_NSB_PROX_BM_L3FWD_4Port_Test</center> </a></h5>\n<center>\n<p>The application does Port forwarding without touching packets. It will take packets in from one port and forward them unmodified to another port </p>\n<p>The KPI is the number of packets per second for a specified packet size with an accepted minimal packet loss </p>\n</center>",
+      "editable": true,
+      "error": false,
+      "gridPos": {
+        "h": 5,
+        "w": 12,
+        "x": 0,
+        "y": 0
+      },
+      "id": 3,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 32px '#31A7D3'\"><center>Test Parameters</center> </a></h5>",
+      "gridPos": {
+        "h": 2,
+        "w": 12,
+        "x": 12,
+        "y": 0
+      },
+      "id": 136,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 3,
+        "x": 12,
+        "y": 2
+      },
+      "height": "35",
+      "id": 12,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.duration"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": "",
+      "title": "Test Interval",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 3,
+        "x": 15,
+        "y": 2
+      },
+      "height": "30",
+      "id": 13,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Test Precision",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.test_precision"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": "",
+      "title": "Test Precision",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 3,
+        "x": 18,
+        "y": 2
+      },
+      "height": "30",
+      "id": 11,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Test Duration",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.test_duration"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": "",
+      "title": "Test Duration",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 3,
+        "x": 21,
+        "y": 2
+      },
+      "height": "30",
+      "id": 14,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Tolerated Loss",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.tolerated_loss"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": "",
+      "title": "Tolerated Loss",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "fill": 1,
+      "gridPos": {
+        "h": 10,
+        "w": 24,
+        "x": 0,
+        "y": 5
+      },
+      "id": 123,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "Cumulative Packets Sents",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.packets_fwd"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(216, 200, 27, 0.27)",
+          "line": true,
+          "lineColor": "rgba(0, 0, 0, 0)",
+          "op": "gt",
+          "value": 0
+        },
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgb(234, 112, 112, 0.22)",
+          "line": true,
+          "lineColor": "rgba(0, 0, 0, 0.01)",
+          "op": "gt",
+          "value": 0
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Cumulative Load Sent by Generator",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "Packets Per Second",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Throughput</center> </a></h5>\n",
+      "editable": true,
+      "error": false,
+      "gridPos": {
+        "h": 3,
+        "w": 24,
+        "x": 0,
+        "y": 15
+      },
+      "height": "40",
+      "id": 7,
+      "links": [],
+      "minSpan": 24,
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 9,
+        "w": 12,
+        "x": 0,
+        "y": 18
+      },
+      "id": 2,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": true,
+      "targets": [
+        {
+          "alias": "Load Requested to Generator",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.RequestedTxThroughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "Load Generated (by the Generator)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.TxThroughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "Load Received (by the Generator)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.RxThroughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(216, 200, 27, 0.27)",
+          "op": "gt",
+          "value": 0
+        },
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(234, 112, 112, 0.22)",
+          "op": "gt",
+          "value": 0
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Generator stats",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "transparent": false,
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "Million Packets Per Second",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": false
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 9,
+        "w": 12,
+        "x": 12,
+        "y": 18
+      },
+      "id": 5,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "sort": "min",
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": true,
+      "targets": [
+        {
+          "alias": "Packet Size",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(216, 200, 27, 0.27)",
+          "op": "gt",
+          "value": 0
+        },
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(234, 112, 112, 0.22)",
+          "op": "gt",
+          "value": 0
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Packet Size",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "none",
+          "label": "Packet Size (Bytes)",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": "%L ine Rate",
+          "logBase": 1,
+          "max": "100",
+          "min": "0",
+          "show": false
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 27
+      },
+      "height": "300",
+      "id": 4,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "rightSide": false,
+        "show": true,
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 1,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": true,
+      "targets": [
+        {
+          "alias": "SUT Packets Received",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "C",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.curr_packets_in"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [
+                  " / 1000000"
+                ],
+                "type": "math"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(216, 200, 27, 0.27)",
+          "op": "gt",
+          "value": 0
+        },
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(234, 112, 112, 0.22)",
+          "op": "gt",
+          "value": 0
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "SUT Stats - Load Received By SUT",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "Million Packets per Second",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 27
+      },
+      "height": "300",
+      "id": 39,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "rightSide": false,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 1,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": true,
+      "targets": [
+        {
+          "alias": "SUT Packets Sent",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.curr_packets_fwd"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              },
+              {
+                "params": [
+                  " / 1000000"
+                ],
+                "type": "math"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(216, 200, 27, 0.27)",
+          "op": "gt",
+          "value": 0
+        },
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(234, 112, 112, 0.22)",
+          "op": "gt",
+          "value": 0
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "SUT Stats - Load Forwarded By SUT",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "Million Packets per Second",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Prox L3FWD Traffic Gen stats</center> </a></h5>\n",
+      "editable": true,
+      "error": false,
+      "gridPos": {
+        "h": 3,
+        "w": 24,
+        "x": 0,
+        "y": 35
+      },
+      "height": "40",
+      "id": 8,
+      "links": [],
+      "minSpan": 24,
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 10,
+        "w": 12,
+        "x": 0,
+        "y": 38
+      },
+      "id": 43,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": true,
+      "targets": [
+        {
+          "alias": "TG xe-0 Out packets",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.xe0.out_packets"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "TG xe-1 Out packets",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.xe1.out_packets"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "TG xe-2 Out packets",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "C",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.xe2.out_packets"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "TG xe-3 Out packets",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "D",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.xe3.out_packets"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(216, 200, 27, 0.27)",
+          "op": "gt",
+          "value": 0
+        },
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(234, 112, 112, 0.22)",
+          "op": "gt",
+          "value": 0
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Packets Sent by Generator",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "Packets ",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 10,
+        "w": 12,
+        "x": 12,
+        "y": 38
+      },
+      "id": 9,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "TG xe-0 in packets",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.xe0.in_packets"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "TG xe-1 in packets",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.xe1.in_packets"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "TG xe-2 in packets",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "C",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.xe2.in_packets"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "TG xe-3 in packets",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "D",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.xe3.in_packets"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(216, 200, 27, 0.27)",
+          "op": "gt",
+          "value": 0
+        },
+        {
+          "colorMode": "custom",
+          "fill": true,
+          "fillColor": "rgba(234, 112, 112, 0.22)",
+          "op": "gt",
+          "value": 0
+        }
+      ],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Packets Received by Generator",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "Packets Per Second",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "fill": 1,
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 48
+      },
+      "id": 10,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "SUCCESS Tx Total",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_tx_total"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "SUCCESS Rx Total",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_rx_total"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "SUCCESS ALLOWABLE LOST PACKETS",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "C",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_can_be_lost"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "SUCCESS CRITERIA: TX Total  = Rx Total + Tolerated Loss",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "Packets Per Second",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "fill": 1,
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 48
+      },
+      "id": 137,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "MAX Line Rate",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.MAX_Rate"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "MIN Line Rate",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.MIN_Rate"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "Current Line Rate",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "C",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Test_Rate"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Line Rate",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "decimals": 4,
+          "format": "short",
+          "label": "Line Rate",
+          "logBase": 1,
+          "max": "100",
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Performance Stats</center> </a></h5>\n",
+      "editable": true,
+      "error": false,
+      "gridPos": {
+        "h": 3,
+        "w": 24,
+        "x": 0,
+        "y": 56
+      },
+      "height": "40",
+      "id": 138,
+      "links": [],
+      "minSpan": 24,
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<style=\"font-family:Verdana\"> <z  style=\"font: 22px'\"><center>Packet size</center> </a>",
+      "gridPos": {
+        "h": 4,
+        "w": 2,
+        "x": 0,
+        "y": 59
+      },
+      "height": "30px",
+      "id": 15,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <z style=\"font: 22px'\"><center>Theoretical Max Throughput (MPPS)</center> </a></h5>\n",
+      "gridPos": {
+        "h": 4,
+        "w": 2,
+        "x": 2,
+        "y": 59
+      },
+      "height": "30px",
+      "id": 16,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <z style=\"font: 22px'\"><center>Tx Throughput (MPPS)</center> </a></h5>",
+      "gridPos": {
+        "h": 4,
+        "w": 2,
+        "x": 4,
+        "y": 59
+      },
+      "height": "30px",
+      "id": 17,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <z style=\"font: 22px'\"><center>Rx Throughput (MPPS)</center></a></h5>",
+      "gridPos": {
+        "h": 4,
+        "w": 2,
+        "x": 6,
+        "y": 59
+      },
+      "height": "30px",
+      "id": 58,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <z style=\"font: 22px'\"><center>Tot Sent </center></a></h5>",
+      "gridPos": {
+        "h": 4,
+        "w": 2,
+        "x": 8,
+        "y": 59
+      },
+      "height": "40px",
+      "id": 61,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <z style=\"font: 22px'\"><center>Tot Received</center></a></h5>",
+      "gridPos": {
+        "h": 4,
+        "w": 2,
+        "x": 10,
+        "y": 59
+      },
+      "height": "30px",
+      "id": 62,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <z style=\"font: 22px'\"><center>Tot Dropped</center></a></h5>",
+      "gridPos": {
+        "h": 4,
+        "w": 2,
+        "x": 12,
+        "y": 59
+      },
+      "height": "30px",
+      "id": 63,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <z style=\"font: 22px'\"><center>Tolerated Loss</center></a></h5>\n",
+      "gridPos": {
+        "h": 4,
+        "w": 2,
+        "x": 14,
+        "y": 59
+      },
+      "height": "30px",
+      "id": 64,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <z style=\"font: 22px'\"><center>Rx Throughput (Gbps)</center></a></h5>",
+      "gridPos": {
+        "h": 4,
+        "w": 2,
+        "x": 16,
+        "y": 59
+      },
+      "height": "30px",
+      "id": 124,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 4,
+        "w": 6,
+        "x": 18,
+        "y": 59
+      },
+      "height": "30px",
+      "id": 125,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "transparent": false,
+      "type": "text"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 0,
+        "y": 63
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 18,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 64) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 2,
+        "y": 63
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 140,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 64 )  AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.theor_max_throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 4,
+        "y": 63
+      },
+      "height": "30px",
+      "id": 20,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 6,
+        "y": 63
+      },
+      "height": "30px",
+      "id": 69,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "last",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "table",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 8,
+        "y": 63
+      },
+      "height": "30px",
+      "id": 70,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 10,
+        "y": 63
+      },
+      "height": "30px",
+      "id": 71,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 12,
+        "y": 63
+      },
+      "height": "30px",
+      "id": 72,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 14,
+        "y": 63
+      },
+      "height": "30px",
+      "id": 73,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 16,
+        "y": 63
+      },
+      "height": "30px",
+      "id": 127,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT mean(\"tg__0.Success_RxThroughput_gbps\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 64) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_RxThroughput_gbps"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 18,
+        "y": 63
+      },
+      "height": "30px",
+      "id": 134,
+      "links": [],
+      "minSpan": 6,
+      "mode": "html",
+      "title": "",
+      "transparent": false,
+      "type": "text"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 0,
+        "y": 66
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 141,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 128) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 2,
+        "y": 66
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 19,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 128 )  AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.theor_max_throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 4,
+        "y": 66
+      },
+      "height": "30px",
+      "id": 142,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 6,
+        "y": 66
+      },
+      "height": "30px",
+      "id": 143,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "last",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "table",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 8,
+        "y": 66
+      },
+      "height": "30px",
+      "id": 144,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 10,
+        "y": 66
+      },
+      "height": "30px",
+      "id": 145,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 12,
+        "y": 66
+      },
+      "height": "30px",
+      "id": 146,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 14,
+        "y": 66
+      },
+      "height": "30px",
+      "id": 147,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 16,
+        "y": 66
+      },
+      "height": "30px",
+      "id": 148,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT mean(\"tg__0.Success_RxThroughput_gbps\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 128) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_RxThroughput_gbps"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 18,
+        "y": 66
+      },
+      "height": "30px",
+      "id": 149,
+      "links": [],
+      "minSpan": 6,
+      "mode": "html",
+      "title": "",
+      "transparent": false,
+      "type": "text"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 0,
+        "y": 69
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 150,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 256) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 2,
+        "y": 69
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 151,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 256 )  AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.theor_max_throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 4,
+        "y": 69
+      },
+      "height": "30px",
+      "id": 152,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 6,
+        "y": 69
+      },
+      "height": "30px",
+      "id": 153,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "last",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "table",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 8,
+        "y": 69
+      },
+      "height": "30px",
+      "id": 154,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 10,
+        "y": 69
+      },
+      "height": "30px",
+      "id": 155,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 12,
+        "y": 69
+      },
+      "height": "30px",
+      "id": 156,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 14,
+        "y": 69
+      },
+      "height": "30px",
+      "id": 198,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 16,
+        "y": 69
+      },
+      "height": "30px",
+      "id": 202,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT mean(\"tg__0.Success_RxThroughput_gbps\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 256) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_RxThroughput_gbps"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 18,
+        "y": 69
+      },
+      "height": "30px",
+      "id": 159,
+      "links": [],
+      "minSpan": 6,
+      "mode": "html",
+      "title": "",
+      "transparent": false,
+      "type": "text"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 0,
+        "y": 72
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 166,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 512) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 2,
+        "y": 72
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 171,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 512)  AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 4,
+        "y": 72
+      },
+      "height": "30px",
+      "id": 162,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 6,
+        "y": 72
+      },
+      "height": "30px",
+      "id": 163,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "last",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "table",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 8,
+        "y": 72
+      },
+      "height": "30px",
+      "id": 164,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 10,
+        "y": 72
+      },
+      "height": "30px",
+      "id": 165,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 12,
+        "y": 72
+      },
+      "height": "30px",
+      "id": 193,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 14,
+        "y": 72
+      },
+      "height": "30px",
+      "id": 157,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 16,
+        "y": 72
+      },
+      "height": "30px",
+      "id": 200,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT mean(\"tg__0.Success_RxThroughput_gbps\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 512) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_RxThroughput_gbps"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 18,
+        "y": 72
+      },
+      "height": "30px",
+      "id": 210,
+      "links": [],
+      "minSpan": 6,
+      "mode": "html",
+      "title": "",
+      "transparent": false,
+      "type": "text"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 0,
+        "y": 75
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 160,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 1024) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 2,
+        "y": 75
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 170,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(tg__0.theor_max_throughput) FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 1024) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 4,
+        "y": 75
+      },
+      "height": "30px",
+      "id": 174,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 6,
+        "y": 75
+      },
+      "height": "30px",
+      "id": 178,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "last",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "table",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 8,
+        "y": 75
+      },
+      "height": "30px",
+      "id": 182,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 10,
+        "y": 75
+      },
+      "height": "30px",
+      "id": 185,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 12,
+        "y": 75
+      },
+      "height": "30px",
+      "id": 191,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 14,
+        "y": 75
+      },
+      "height": "30px",
+      "id": 195,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 16,
+        "y": 75
+      },
+      "height": "30px",
+      "id": 203,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT mean(\"tg__0.Success_RxThroughput_gbps\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 1024) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_RxThroughput_gbps"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 18,
+        "y": 75
+      },
+      "height": "30px",
+      "id": 209,
+      "links": [],
+      "minSpan": 6,
+      "mode": "html",
+      "title": "",
+      "transparent": false,
+      "type": "text"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 0,
+        "y": 78
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 168,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 1280) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 2,
+        "y": 78
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 172,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 1280 )  AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.theor_max_throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 4,
+        "y": 78
+      },
+      "height": "30px",
+      "id": 175,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 6,
+        "y": 78
+      },
+      "height": "30px",
+      "id": 179,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "last",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "table",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 8,
+        "y": 78
+      },
+      "height": "30px",
+      "id": 183,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 10,
+        "y": 78
+      },
+      "height": "30px",
+      "id": 186,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 12,
+        "y": 78
+      },
+      "height": "30px",
+      "id": 190,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 14,
+        "y": 78
+      },
+      "height": "30px",
+      "id": 196,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 16,
+        "y": 78
+      },
+      "height": "30px",
+      "id": 204,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT mean(\"tg__0.Success_RxThroughput_gbps\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 1280) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_RxThroughput_gbps"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 18,
+        "y": 78
+      },
+      "height": "30px",
+      "id": 208,
+      "links": [],
+      "minSpan": 6,
+      "mode": "html",
+      "title": "",
+      "transparent": false,
+      "type": "text"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 0,
+        "y": 81
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 167,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 1518) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 2,
+        "y": 81
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 173,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 1518 )  AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.theor_max_throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 4,
+        "y": 81
+      },
+      "height": "30px",
+      "id": 176,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518  AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 6,
+        "y": 81
+      },
+      "height": "30px",
+      "id": 180,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "last",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "table",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 8,
+        "y": 81
+      },
+      "height": "30px",
+      "id": 187,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 10,
+        "y": 81
+      },
+      "height": "30px",
+      "id": 184,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 12,
+        "y": 81
+      },
+      "height": "30px",
+      "id": 194,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 14,
+        "y": 81
+      },
+      "height": "30px",
+      "id": 197,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 16,
+        "y": 81
+      },
+      "height": "30px",
+      "id": 158,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT mean(\"tg__0.Success_RxThroughput_gbps\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 1518) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_RxThroughput_gbps"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 18,
+        "y": 81
+      },
+      "height": "30px",
+      "id": 206,
+      "links": [],
+      "minSpan": 6,
+      "mode": "html",
+      "title": "",
+      "transparent": false,
+      "type": "text"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 0,
+        "y": 84
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 169,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 2048) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.PktSize"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "last"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 2,
+        "y": 84
+      },
+      "height": "30px",
+      "hideTimeOverride": false,
+      "id": 161,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "alias": "Theoretical Max Throughput  (Mpps)",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": false,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 2048 )  AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.theor_max_throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 4,
+        "y": 84
+      },
+      "height": "30px",
+      "id": 177,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 2048 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 6,
+        "y": 84
+      },
+      "height": "30px",
+      "id": 181,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "last",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 2048  AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "table",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 8,
+        "y": 84
+      },
+      "height": "30px",
+      "id": 188,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 2048 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 10,
+        "y": 84
+      },
+      "height": "30px",
+      "id": 189,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 2048 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 12,
+        "y": 84
+      },
+      "height": "30px",
+      "id": 192,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 2048 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 0,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 14,
+        "y": 84
+      },
+      "height": "30px",
+      "id": 199,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 2048 AND $timeFilter",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_Throughput"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "rgba(50, 172, 45, 0.97)"
+      ],
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 4,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 2,
+        "x": 16,
+        "y": 84
+      },
+      "height": "30px",
+      "id": 205,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT mean(\"tg__0.Success_RxThroughput_gbps\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE (\"tg__0.PktSize\" = 2048) AND $timeFilter GROUP BY time($__interval) fill(null)",
+          "rawQuery": true,
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.Success_RxThroughput_gbps"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": [
+            {
+              "key": "tg__0.PktSize",
+              "operator": "=",
+              "value": "64"
+            }
+          ]
+        }
+      ],
+      "thresholds": "",
+      "title": "",
+      "type": "singlestat",
+      "valueFontSize": "50%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "avg"
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 18,
+        "y": 84
+      },
+      "height": "30px",
+      "id": 207,
+      "links": [],
+      "minSpan": 6,
+      "mode": "html",
+      "title": "",
+      "transparent": false,
+      "type": "text"
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Latency</center> </a></h5>",
+      "gridPos": {
+        "h": 3,
+        "w": 24,
+        "x": 0,
+        "y": 87
+      },
+      "height": "40",
+      "id": 41,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "fill": 1,
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 90
+      },
+      "height": "300px",
+      "id": 47,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "xe0 Latency Avg",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.LatencyAvg.5"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "xe0 Latency Max",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.LatencyMax.5"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "xe0 Latency",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "usec",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "fill": 1,
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 90
+      },
+      "height": "300px",
+      "id": 48,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "xe1 Latency Avg",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.LatencyAvg.5"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "xe1 Latency Max",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.LatencyAvg.6"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "xe1 Latency",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "usec",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "fill": 1,
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 98
+      },
+      "height": "300px",
+      "id": 49,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "xe2 Latency Avg",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.LatencyAvg.7"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "xe2 Latency Max",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.LatencyAvg.7"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "xe2 Latency",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "usec",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "fill": 1,
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 98
+      },
+      "height": "300px",
+      "id": 211,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": true,
+        "min": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "xe2 Latency Avg",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.LatencyAvg.8"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "xe2 Latency Max",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "null"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "tg__0.LatencyMax.8"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "mean"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "xe2 Latency",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": "usec",
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>SUT CPU Utilization</center> </a></h5>",
+      "gridPos": {
+        "h": 3,
+        "w": 24,
+        "x": 0,
+        "y": 106
+      },
+      "height": "40px",
+      "id": 51,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "type": "text"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_YARDSTICK}",
+      "decimals": 5,
+      "fill": 1,
+      "gridPos": {
+        "h": 11,
+        "w": 12,
+        "x": 0,
+        "y": 109
+      },
+      "height": "900px",
+      "id": 53,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "show": true,
+        "sort": "avg",
+        "sortDesc": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "CPU 0 - Master",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "B",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.0.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 1 - RX:p0 - Routing - TX:p0,p1",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "A",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.1.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 2 - RX:p1 - Routing - TX:p0,p1",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "C",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.2.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 3 - RX:p2 - Routing - TX:p2,p3",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT distinct(\"vnf__0.collect_stats.core.cpu.3.percent-user\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($__interval) fill(none)",
+          "rawQuery": false,
+          "refId": "D",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.3.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 4 - RX:p3 - Routing - TX:p2,p3",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "query": "SELECT distinct(\"vnf__0.collect_stats.core.cpu.4.percent-user\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($__interval) fill(none)",
+          "rawQuery": false,
+          "refId": "E",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.4.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU  5",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "F",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.5.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 6",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "G",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.6.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 7",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "H",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.7.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 8",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "I",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.8.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 9",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "J",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.9.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 10",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "K",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.10.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 11",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "L",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.11.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 12",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "M",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.12.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 13",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "N",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.13.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 14",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "O",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.14.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 15",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "P",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.15.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        },
+        {
+          "alias": "CPU 16",
+          "dsType": "influxdb",
+          "groupBy": [
+            {
+              "params": [
+                "$__interval"
+              ],
+              "type": "time"
+            },
+            {
+              "params": [
+                "none"
+              ],
+              "type": "fill"
+            }
+          ],
+          "hide": true,
+          "measurement": "tc_prox_baremetal_l3fwd-4",
+          "orderByTime": "ASC",
+          "policy": "default",
+          "refId": "Q",
+          "resultFormat": "time_series",
+          "select": [
+            [
+              {
+                "params": [
+                  "vnf__0.collect_stats.core.cpu.17.percent-user"
+                ],
+                "type": "field"
+              },
+              {
+                "params": [],
+                "type": "distinct"
+              }
+            ]
+          ],
+          "tags": []
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "SUT CPU Utilization",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "percent",
+          "label": "% Utilization",
+          "logBase": 1,
+          "max": "100",
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": false
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "content": "",
+      "gridPos": {
+        "h": 3,
+        "w": 6,
+        "x": 0,
+        "y": 120
+      },
+      "height": "30px",
+      "id": 133,
+      "links": [],
+      "mode": "html",
+      "title": "",
+      "transparent": true,
+      "type": "text"
+    }
+  ],
+  "refresh": "5s",
+  "schemaVersion": 16,
+  "style": "dark",
+  "tags": [
+    "yardstick",
+    "NSB",
+    "Prox",
+    "l3fwd",
+    "4Port",
+    "BM"
+  ],
+  "templating": {
+    "list": []
+  },
+  "time": {
+    "from": "now-1h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "browser",
+  "title": "Prox_BM_l3fwd-4Port",
+  "uid": "G-hksJHmz",
+  "version": 13
+}
\ No newline at end of file
diff --git a/dashboard/Prox_BM_vPE-4Port-1507804058631.json b/dashboard/Prox_BM_vPE-4Port-1507804058631.json
deleted file mode 100644 (file)
index 52afcae..0000000
+++ /dev/null
@@ -1,1163 +0,0 @@
-{
-  "__inputs": [
-    {
-      "name": "DS_YARDSTICK",
-      "label": "yardstick",
-      "description": "",
-      "type": "datasource",
-      "pluginId": "influxdb",
-      "pluginName": "InfluxDB"
-    }
-  ],
-  "__requires": [
-    {
-      "type": "grafana",
-      "id": "grafana",
-      "name": "Grafana",
-      "version": "4.4.3"
-    },
-    {
-      "type": "panel",
-      "id": "graph",
-      "name": "Graph",
-      "version": ""
-    },
-    {
-      "type": "datasource",
-      "id": "influxdb",
-      "name": "InfluxDB",
-      "version": "1.0.0"
-    },
-    {
-      "type": "panel",
-      "id": "text",
-      "name": "Text",
-      "version": ""
-    }
-  ],
-  "annotations": {
-    "list": []
-  },
-  "editable": true,
-  "gnetId": null,
-  "graphTooltip": 0,
-  "hideControls": false,
-  "id": null,
-  "links": [],
-  "refresh": false,
-  "rows": [
-    {
-      "collapse": false,
-      "height": "100px",
-      "panels": [
-        {
-          "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 32px '#31A7D3'\"><center>OPNFV_Yardstick_NSB_PROX_BM_vPE_4Port_Test</center> </a></h5>\n<center>\n<p>The vPE handles packet processing, routing, QinQ encapsulation, flows, ACL rules, adds/removes MPLS tags and performs QoS </p>\n<p>The KPI is the number of packets per second for a specified packet size (min packet size is 68 byte) with an accepted minimal packet loss</p>\n</center>",
-          "editable": true,
-          "error": false,
-          "id": 3,
-          "links": [],
-          "mode": "html",
-          "span": 12,
-          "title": "",
-          "type": "text"
-        },
-        {
-          "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Prox vPE VNF stats</center> </a></h5>\n",
-          "editable": true,
-          "error": false,
-          "height": "40",
-          "id": 7,
-          "links": [],
-          "mode": "html",
-          "span": 12,
-          "title": "",
-          "type": "text"
-        }
-      ],
-      "repeat": null,
-      "repeatIteration": null,
-      "repeatRowId": null,
-      "showTitle": false,
-      "title": "Row",
-      "titleSize": "h6"
-    },
-    {
-      "collapse": false,
-      "height": "300px",
-      "panels": [
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "editable": true,
-          "error": false,
-          "fill": 1,
-          "grid": {},
-          "height": "300",
-          "id": 4,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "rightSide": false,
-            "show": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 1,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 12,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
-            {
-              "alias": "VNF packets Forward",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "A",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "vnf__0.packets_fwd"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            },
-            {
-              "alias": "VNF packets in",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "C",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "vnf__0.packets_in"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            },
-            {
-              "alias": "VNF packets dropped",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "B",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "vnf__0.packets_dropped"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            }
-          ],
-          "thresholds": [
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(216, 200, 27, 0.27)",
-              "op": "gt",
-              "value": 2
-            },
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(234, 112, 112, 0.22)",
-              "op": "gt",
-              "value": 2
-            }
-          ],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "vPE VNF stats",
-          "tooltip": {
-            "msResolution": true,
-            "shared": true,
-            "sort": 0,
-            "value_type": "cumulative"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
-            {
-              "format": "short",
-              "label": "Packets",
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            },
-            {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            }
-          ]
-        },
-        {
-          "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Prox vPE Traffic Gen stats</center> </a></h5>\n",
-          "editable": true,
-          "error": false,
-          "height": "40",
-          "id": 8,
-          "links": [],
-          "mode": "html",
-          "span": 12,
-          "title": "",
-          "type": "text"
-        }
-      ],
-      "repeat": null,
-      "repeatIteration": null,
-      "repeatRowId": null,
-      "showTitle": false,
-      "title": "New row",
-      "titleSize": "h6"
-    },
-    {
-      "collapse": false,
-      "height": "300px",
-      "panels": [
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "editable": true,
-          "error": false,
-          "fill": 1,
-          "grid": {},
-          "id": 6,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "show": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 5,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 6,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
-            {
-              "alias": "TG xe-0 Out packets",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "A",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.xe0.out_packets"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            },
-            {
-              "alias": "TG xe-1 Out packets",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "B",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.xe1.out_packets"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            },
-            {
-              "alias": "TG xe-2 Out packets",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "C",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.xe2.out_packets"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            },
-            {
-              "alias": "TG xe-3 Out packets",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "D",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.xe3.out_packets"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            }
-          ],
-          "thresholds": [
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(216, 200, 27, 0.27)",
-              "op": "gt",
-              "value": 2
-            },
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(234, 112, 112, 0.22)",
-              "op": "gt",
-              "value": 2
-            }
-          ],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "TG Port Stats:  Out packets",
-          "tooltip": {
-            "msResolution": true,
-            "shared": true,
-            "sort": 0,
-            "value_type": "cumulative"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
-            {
-              "format": "short",
-              "label": "Packets ",
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            },
-            {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            }
-          ]
-        },
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "editable": true,
-          "error": false,
-          "fill": 1,
-          "grid": {},
-          "id": 9,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "show": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 5,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 6,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
-            {
-              "alias": "TG xe-0 in packets",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "A",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.xe0.in_packets"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            },
-            {
-              "alias": "TG xe-1 in packets",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "B",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.xe1.in_packets"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            },
-            {
-              "alias": "TG xe-2 in packets",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "C",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.xe2.in_packets"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            },
-            {
-              "alias": "TG xe-3 in packets",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "D",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.xe3.in_packets"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            }
-          ],
-          "thresholds": [
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(216, 200, 27, 0.27)",
-              "op": "gt",
-              "value": 2
-            },
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(234, 112, 112, 0.22)",
-              "op": "gt",
-              "value": 2
-            }
-          ],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "TG Port Stats: In packets",
-          "tooltip": {
-            "msResolution": true,
-            "shared": true,
-            "sort": 0,
-            "value_type": "cumulative"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
-            {
-              "format": "short",
-              "label": "Packets ",
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            },
-            {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            }
-          ]
-        }
-      ],
-      "repeat": null,
-      "repeatIteration": null,
-      "repeatRowId": null,
-      "showTitle": false,
-      "title": "New row",
-      "titleSize": "h6"
-    },
-    {
-      "collapse": false,
-      "height": "250px",
-      "panels": [
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "editable": true,
-          "error": false,
-          "fill": 1,
-          "grid": {},
-          "id": 2,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "show": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 5,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 6,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
-            {
-              "alias": "TX Throughput",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "A",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.TxThroughput"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            },
-            {
-              "alias": "RX Throughput",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "B",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.RxThroughput"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            }
-          ],
-          "thresholds": [
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(216, 200, 27, 0.27)",
-              "op": "gt",
-              "value": 2
-            },
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(234, 112, 112, 0.22)",
-              "op": "gt",
-              "value": 2
-            }
-          ],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "TG Tx vs Rx Throughput",
-          "tooltip": {
-            "msResolution": true,
-            "shared": true,
-            "sort": 0,
-            "value_type": "cumulative"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
-            {
-              "format": "short",
-              "label": "Throughput in MPPS",
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            },
-            {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            }
-          ]
-        },
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "editable": true,
-          "error": false,
-          "fill": 1,
-          "grid": {},
-          "id": 5,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "show": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 5,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 6,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
-            {
-              "alias": "Packet Size",
-              "dsType": "influxdb",
-              "groupBy": [
-                {
-                  "params": [
-                    "$interval"
-                  ],
-                  "type": "time"
-                },
-                {
-                  "params": [
-                    "null"
-                  ],
-                  "type": "fill"
-                }
-              ],
-              "measurement": "tc_prox_baremetal_vpe-4",
-              "orderByTime": "ASC",
-              "policy": "default",
-              "refId": "A",
-              "resultFormat": "time_series",
-              "select": [
-                [
-                  {
-                    "params": [
-                      "tg__0.PktSize"
-                    ],
-                    "type": "field"
-                  },
-                  {
-                    "params": [],
-                    "type": "mean"
-                  }
-                ]
-              ],
-              "tags": []
-            }
-          ],
-          "thresholds": [
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(216, 200, 27, 0.27)",
-              "op": "gt",
-              "value": 2
-            },
-            {
-              "colorMode": "custom",
-              "fill": true,
-              "fillColor": "rgba(234, 112, 112, 0.22)",
-              "op": "gt",
-              "value": 2
-            }
-          ],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "Packet size",
-          "tooltip": {
-            "msResolution": true,
-            "shared": true,
-            "sort": 0,
-            "value_type": "cumulative"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
-            {
-              "format": "bytes",
-              "label": "Packet Size",
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            },
-            {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": null,
-              "show": true
-            }
-          ]
-        }
-      ],
-      "repeat": null,
-      "repeatIteration": null,
-      "repeatRowId": null,
-      "showTitle": false,
-      "title": "New row",
-      "titleSize": "h6"
-    },
-    {
-      "collapse": false,
-      "height": "250px",
-      "panels": [],
-      "repeat": null,
-      "repeatIteration": null,
-      "repeatRowId": null,
-      "showTitle": false,
-      "title": "New row",
-      "titleSize": "h6"
-    }
-  ],
-  "schemaVersion": 14,
-  "style": "dark",
-  "tags": [
-    "yardstick",
-    "NSB",
-    "Prox",
-    "4Port",
-    "BM",
-    "vPE"
-  ],
-  "templating": {
-    "list": []
-  },
-  "time": {
-    "from": "2017-10-09T11:05:30.701Z",
-    "to": "2017-10-09T11:11:21.952Z"
-  },
-  "timepicker": {
-    "refresh_intervals": [
-      "5s",
-      "10s",
-      "30s",
-      "1m",
-      "5m",
-      "15m",
-      "30m",
-      "1h",
-      "2h",
-      "1d"
-    ],
-    "time_options": [
-      "5m",
-      "15m",
-      "1h",
-      "6h",
-      "12h",
-      "24h",
-      "2d",
-      "7d",
-      "30d"
-    ]
-  },
-  "timezone": "browser",
-  "title": "Prox_BM_vPE-4Port",
-  "version": 10
-}
\ No newline at end of file
@@ -2,7 +2,7 @@
   "__inputs": [
     {
       "name": "DS_YARDSTICK",
-      "label": "YARDSTICK",
+      "label": "yardstick",
       "description": "",
       "type": "datasource",
       "pluginId": "influxdb",
   "hideControls": false,
   "id": null,
   "links": [],
-  "refresh": "5s",
+  "refresh": false,
   "rows": [
     {
       "collapse": false,
       "height": "100px",
       "panels": [
         {
-          "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 32px '#31A7D3'\"><center>OPNFV_Yardstick_NSB_PROX_BM_L3FWD_4Port_Test</center> </a></h5>\n<center>\n<p>The application does Port forwarding without touching packets. It will take packets in from one port and forward them unmodified to another port </p>\n<p>The KPI is the number of packets per second for a specified packet size with an accepted minimal packet loss </p>\n</center>",
+          "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 32px '#31A7D3'\"><center>OPNFV_Yardstick_NSB_PROX_BM_vPE_4Port_Test</center> </a></h5>\n<center>\n<p>The application does Port forwarding without touching packets. It will take packets in from one port and forward them unmodified to another port </p>\n<p>The KPI is the number of packets per second for a specified packet size with an accepted minimal packet loss </p>\n</center>",
           "editable": true,
           "error": false,
           "id": 3,
@@ -76,7 +76,7 @@
       "titleSize": "h6"
     },
     {
-      "collapse": true,
+      "collapse": false,
       "height": 362,
       "panels": [
         {
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
           "renderer": "flot",
           "seriesOverrides": [],
           "spaceLength": 10,
-          "span": 7,
+          "span": 6,
           "stack": false,
           "steppedLine": true,
           "targets": [
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                 }
               ],
               "hide": false,
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "B",
             "max": true,
             "min": true,
             "show": true,
+            "sort": "min",
+            "sortDesc": true,
             "total": false,
             "values": true
           },
           "renderer": "flot",
           "seriesOverrides": [],
           "spaceLength": 10,
-          "span": 5,
+          "span": 6,
           "stack": false,
           "steppedLine": true,
           "targets": [
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                 ]
               ],
               "tags": []
+            },
+            {
+              "alias": "MAX Line Rate",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "null"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "B",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "tg__0.MAX_Rate"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "mean"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "MIN Line Rate",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "null"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "C",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "tg__0.MIN_Rate"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "mean"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "Test Rate",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "null"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "D",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "tg__0.Test_Rate"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "mean"
+                  }
+                ]
+              ],
+              "tags": []
             }
           ],
           "thresholds": [
           ],
           "timeFrom": null,
           "timeShift": null,
-          "title": "Packet size",
+          "title": "Packet size & Percent of  Line Rate",
           "tooltip": {
             "msResolution": true,
             "shared": true,
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "C",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
       "height": 289,
       "panels": [
         {
-          "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Prox L3Fwd Traffic Gen stats</center> </a></h5>\n",
+          "content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Prox VPE Traffic Gen stats</center> </a></h5>\n",
           "editable": true,
           "error": false,
           "height": "40",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "B",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "C",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "D",
           "renderer": "flot",
           "seriesOverrides": [],
           "spaceLength": 10,
-          "span": 5,
+          "span": 6,
           "stack": false,
           "steppedLine": false,
           "targets": [
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "B",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "C",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "D",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "B",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "C",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                 }
               ],
               "hide": false,
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter GROUP BY time($__interval) fill(null)",
+              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 68 AND $timeFilter GROUP BY time($__interval) fill(null)",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Result_pktSize\" = 64 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.theor_max_throughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 68 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                 [
                   {
                     "params": [
-                      "tg__0.Result_theor_max_throughput"
+                      "tg__0.theor_max_throughput"
                     ],
                     "type": "field"
                   },
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 68 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 68 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "table",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 68 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 68 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 68 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 64 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 68 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                 }
               ],
               "hide": false,
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter GROUP BY time($__interval) fill(null)",
+              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter GROUP BY time($__interval) fill(null)",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Result_pktSize\" = 128 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Result_pktSize\" = 128 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 128 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                 }
               ],
               "hide": false,
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter GROUP BY time($__interval) fill(null)",
+              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter GROUP BY time($__interval) fill(null)",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Result_pktSize\" = 256 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Result_pktSize\" = 256 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 256 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                 }
               ],
               "hide": false,
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter GROUP BY time($__interval) fill(null)",
+              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter GROUP BY time($__interval) fill(null)",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Result_pktSize\" = 512 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Result_pktSize\" = 512 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 512 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                 }
               ],
               "hide": false,
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter GROUP BY time($__interval) fill(null)",
+              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter GROUP BY time($__interval) fill(null)",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Result_pktSize\" = 1024 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Result_pktSize\" = 1024 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1024 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                 }
               ],
               "hide": false,
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter GROUP BY time($__interval) fill(null)",
+              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter GROUP BY time($__interval) fill(null)",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Result_pktSize\" = 1280 AND $timeFilter AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Result_pktSize\" = 1280 AND $timeFilter AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1280 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                 }
               ],
               "hide": false,
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter GROUP BY time($__interval) fill(null)",
+              "query": "SELECT mean(\"tg__0.Success_PktSize\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter GROUP BY time($__interval) fill(null)",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Result_pktSize\" = 1518 AND $timeFilter AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Result_theor_max_throughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Result_pktSize\" = 1518 AND $timeFilter AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_TxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_RxThroughput\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_tx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_rx_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_drop_total\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
+              "query": "SELECT last(\"tg__0.Success_can_be_lost\") FROM \"tc_prox_baremetal_vpe-4\" WHERE \"tg__0.Success_PktSize\" = 1518 AND $timeFilter",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "B",
                 [
                   {
                     "params": [
-                      "tg__0.LatencyAvg.5"
+                      "tg__0.LatencyAvg.9"
                     ],
                     "type": "field"
                   },
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                 [
                   {
                     "params": [
-                      "tg__0.LatencyMax.5"
+                      "tg__0.LatencyMax.9"
                     ],
                     "type": "field"
                   },
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "B",
                 [
                   {
                     "params": [
-                      "tg__0.LatencyAvg.6"
+                      "tg__0.LatencyAvg.10"
                     ],
                     "type": "field"
                   },
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                 [
                   {
                     "params": [
-                      "tg__0.LatencyMax.6"
+                      "tg__0.LatencyMax.10"
                     ],
                     "type": "field"
                   },
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "B",
                 [
                   {
                     "params": [
-                      "tg__0.LatencyAvg.7"
+                      "tg__0.LatencyAvg.11"
                     ],
                     "type": "field"
                   },
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                 [
                   {
                     "params": [
-                      "tg__0.LatencyMax.7"
+                      "tg__0.LatencyMax.11"
                     ],
                     "type": "field"
                   },
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "B",
                 [
                   {
                     "params": [
-                      "tg__0.LatencyAvg.8"
+                      "tg__0.LatencyAvg.12"
                     ],
                     "type": "field"
                   },
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "A",
                 [
                   {
                     "params": [
-                      "tg__0.LatencyMax.8"
+                      "tg__0.LatencyMax.12"
                     ],
                     "type": "field"
                   },
           "datasource": "${DS_YARDSTICK}",
           "decimals": 5,
           "fill": 1,
-          "height": "300px",
-          "id": 52,
+          "height": "900px",
+          "id": 53,
           "legend": {
             "alignAsTable": true,
             "avg": true,
             "max": true,
             "min": true,
             "show": true,
-            "sortDesc": false,
+            "sort": "avg",
+            "sortDesc": true,
             "total": false,
             "values": true
           },
           "steppedLine": false,
           "targets": [
             {
-              "alias": "CPU 0 Utilization",
+              "alias": "CPU 0 - Master",
               "dsType": "influxdb",
               "groupBy": [
                 {
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
               "refId": "B",
                 ]
               ],
               "tags": []
-            }
-          ],
-          "thresholds": [],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "CPU 0 Utilization  - Master Core",
-          "tooltip": {
-            "shared": true,
-            "sort": 0,
-            "value_type": "individual"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
-            {
-              "format": "short",
-              "label": "% Utilization",
-              "logBase": 1,
-              "max": "100",
-              "min": "0",
-              "show": true
             },
             {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": "0",
-              "show": true
-            }
-          ]
-        },
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "decimals": 5,
-          "fill": 1,
-          "height": "300px",
-          "id": 53,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "show": true,
-            "sortDesc": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 5,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 6,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
-            {
-              "alias": "CPU 1 Utilization  - L3FWD XE0 to XE1",
+              "alias": "CPU 1 - RX:inet0 - lbnetwork",
               "dsType": "influxdb",
               "groupBy": [
                 {
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "refId": "B",
+              "refId": "A",
               "resultFormat": "time_series",
               "select": [
                 [
                 ]
               ],
               "tags": []
-            }
-          ],
-          "thresholds": [],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "CPU 1 Utilization  - L3FWD XE0 to XE1",
-          "tooltip": {
-            "shared": true,
-            "sort": 0,
-            "value_type": "individual"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
+            },
             {
-              "format": "short",
-              "label": "% Utilization",
-              "logBase": 1,
-              "max": "100",
-              "min": "0",
-              "show": true
+              "alias": "CPU  2 - RX:inet1 - lbnetwork",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "C",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.2.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
             },
             {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": "0",
-              "show": true
-            }
-          ]
-        },
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "decimals": 5,
-          "fill": 1,
-          "height": "300px",
-          "id": 54,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "show": true,
-            "sortDesc": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 5,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 6,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
+              "alias": "CPU  3 - RX:cpe0 - lbnetwork",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "query": "SELECT distinct(\"vnf__0.collect_stats.core.cpu.3.percent-user\") FROM \"tc_prox_baremetal_vpe-4\" WHERE $timeFilter GROUP BY time($__interval) fill(none)",
+              "rawQuery": false,
+              "refId": "D",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.3.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "CPU  4 - RX:cpe1 - lbnetwork",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "query": "SELECT distinct(\"vnf__0.collect_stats.core.cpu.4.percent-user\") FROM \"tc_prox_baremetal_vpe-4\" WHERE $timeFilter GROUP BY time($__interval) fill(none)",
+              "rawQuery": false,
+              "refId": "E",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.4.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "CPU  5 - TX:cpe0 - QoS",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "F",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.5.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "CPU 6 - TX:inet0",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "G",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.6.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "CPU 7 - TX:cpe1 - QoS",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "H",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.7.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "CPU 8 - TX:inet1",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "I",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.8.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "CPU 9 - Worker Downstream - qinqencapv4",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "J",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.9.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "CPU 10 - Worker Downstream - qinqencapv4",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "K",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.10.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "CPU 11 - Worker Downstream - qinqencapv4",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "L",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.11.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
             {
-              "alias": "CPU 2 Utilization",
+              "alias": "CPU 12 - Worker Downstream - qinqencapv4",
               "dsType": "influxdb",
               "groupBy": [
                 {
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "refId": "B",
+              "refId": "M",
               "resultFormat": "time_series",
               "select": [
                 [
                   {
                     "params": [
-                      "vnf__0.collect_stats.core.cpu.2.percent-user"
+                      "vnf__0.collect_stats.core.cpu.12.percent-user"
                     ],
                     "type": "field"
                   },
                 ]
               ],
               "tags": []
-            }
-          ],
-          "thresholds": [],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "CPU 2 Utilization  - L3FWD XE1 to XE0",
-          "tooltip": {
-            "shared": true,
-            "sort": 0,
-            "value_type": "individual"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
-            {
-              "format": "short",
-              "label": "% Utilization",
-              "logBase": 1,
-              "max": "100",
-              "min": "0",
-              "show": true
             },
             {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": "0",
-              "show": true
-            }
-          ]
-        },
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "decimals": 5,
-          "fill": 1,
-          "height": "300px",
-          "id": 55,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "show": true,
-            "sortDesc": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 5,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 6,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
-            {
-              "alias": "CPU 3 Utilization",
+              "alias": "CPU 13 - Worker Upstream - acl,  police, untag and routing",
               "dsType": "influxdb",
               "groupBy": [
                 {
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "refId": "B",
+              "refId": "N",
               "resultFormat": "time_series",
               "select": [
                 [
                   {
                     "params": [
-                      "vnf__0.collect_stats.core.cpu.3.percent-user"
+                      "vnf__0.collect_stats.core.cpu.13.percent-user"
                     ],
                     "type": "field"
                   },
                 ]
               ],
               "tags": []
-            }
-          ],
-          "thresholds": [],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "CPU 3 Utilization  - L3FWD XE2 to XE3",
-          "tooltip": {
-            "shared": true,
-            "sort": 0,
-            "value_type": "individual"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
-            {
-              "format": "short",
-              "label": "% Utilization",
-              "logBase": 1,
-              "max": "100",
-              "min": "0",
-              "show": true
             },
             {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": "0",
-              "show": true
-            }
-          ]
-        },
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "decimals": 5,
-          "fill": 1,
-          "height": "300px",
-          "id": 56,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "show": true,
-            "sortDesc": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 5,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 6,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
-            {
-              "alias": "CPU 4 Utilization",
+              "alias": "CPU 14 - Worker Upstream - acl,  police, untag and routing",
               "dsType": "influxdb",
               "groupBy": [
                 {
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "refId": "B",
+              "refId": "O",
               "resultFormat": "time_series",
               "select": [
                 [
                   {
                     "params": [
-                      "vnf__0.collect_stats.core.cpu.4.percent-user"
+                      "vnf__0.collect_stats.core.cpu.14.percent-user"
                     ],
                     "type": "field"
                   },
                 ]
               ],
               "tags": []
-            }
-          ],
-          "thresholds": [],
-          "timeFrom": null,
-          "timeShift": null,
-          "title": "CPU 4 Utilization  - L3FWD XE3 to XE2",
-          "tooltip": {
-            "shared": true,
-            "sort": 0,
-            "value_type": "individual"
-          },
-          "type": "graph",
-          "xaxis": {
-            "buckets": null,
-            "mode": "time",
-            "name": null,
-            "show": true,
-            "values": []
-          },
-          "yaxes": [
-            {
-              "format": "short",
-              "label": "% Utilization",
-              "logBase": 1,
-              "max": "100",
-              "min": "0",
-              "show": true
             },
             {
-              "format": "short",
-              "label": null,
-              "logBase": 1,
-              "max": null,
-              "min": "0",
-              "show": true
-            }
-          ]
-        },
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "decimals": 5,
-          "fill": 1,
-          "height": "300px",
-          "id": 57,
-          "legend": {
-            "alignAsTable": true,
-            "avg": true,
-            "current": false,
-            "max": true,
-            "min": true,
-            "show": true,
-            "sortDesc": true,
-            "total": false,
-            "values": true
-          },
-          "lines": true,
-          "linewidth": 2,
-          "links": [],
-          "nullPointMode": "connected",
-          "percentage": false,
-          "pointradius": 5,
-          "points": false,
-          "renderer": "flot",
-          "seriesOverrides": [],
-          "spaceLength": 10,
-          "span": 6,
-          "stack": false,
-          "steppedLine": false,
-          "targets": [
+              "alias": "CPU 15 - Worker Upstream - acl,  police, untag and routing",
+              "dsType": "influxdb",
+              "groupBy": [
+                {
+                  "params": [
+                    "$__interval"
+                  ],
+                  "type": "time"
+                },
+                {
+                  "params": [
+                    "none"
+                  ],
+                  "type": "fill"
+                }
+              ],
+              "measurement": "tc_prox_baremetal_vpe-4",
+              "orderByTime": "ASC",
+              "policy": "default",
+              "refId": "P",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "vnf__0.collect_stats.core.cpu.15.percent-user"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "distinct"
+                  }
+                ]
+              ],
+              "tags": []
+            },
             {
-              "alias": "CPU 5 Utilization",
+              "alias": "CPU 16 - Worker Upstream - acl,  police, untag and routing",
               "dsType": "influxdb",
               "groupBy": [
                 {
                   "type": "fill"
                 }
               ],
-              "measurement": "tc_prox_baremetal_l3fwd-4",
+              "measurement": "tc_prox_baremetal_vpe-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "refId": "B",
+              "refId": "Q",
               "resultFormat": "time_series",
               "select": [
                 [
                   {
                     "params": [
-                      "vnf__0.collect_stats.core.cpu.5.percent-user"
+                      "vnf__0.collect_stats.core.cpu.17.percent-user"
                     ],
                     "type": "field"
                   },
           "thresholds": [],
           "timeFrom": null,
           "timeShift": null,
-          "title": "CPU 5 Utilization",
+          "title": "SUT CPU Utilization",
           "tooltip": {
             "shared": true,
             "sort": 0,
     "yardstick",
     "NSB",
     "Prox",
-    "L3fwd",
+    "vpe",
     "4Port",
     "BM"
   ],
     "list": []
   },
   "time": {
-    "from": "now-30m",
-    "to": "now"
+    "from": "2018-06-18T16:42:35.488Z",
+    "to": "2018-06-18T17:57:41.922Z"
   },
   "timepicker": {
     "refresh_intervals": [
     ]
   },
   "timezone": "browser",
-  "title": "Prox_BM_L3FWD-4Port",
-  "version": 24
+  "title": "Prox_BM_vpe-4Port",
+  "version": 7
 }
\ No newline at end of file
index 7f85cbd..097bc3c 100644 (file)
@@ -26,7 +26,7 @@ ENV YARDSTICK_REPO_DIR="${REPOS_DIR}/yardstick/" \
 
 RUN apt-get update && apt-get install -y git python python-setuptools python-pip iputils-ping && apt-get -y autoremove && apt-get clean
 RUN easy_install -U setuptools==30.0.0
-RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 python-openstackclient==3.11.0 python-heatclient==1.11.0 ansible==2.4.2
+RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 python-openstackclient==3.12.0 python-heatclient==1.11.0 ansible==2.5.5
 
 RUN mkdir -p ${REPOS_DIR}
 
@@ -40,7 +40,7 @@ RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/yardstick ${Y
 RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/releng ${RELENG_REPO_DIR}
 RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/storperf ${STORPERF_REPO_DIR}
 
-RUN ansible-playbook -c local -vvv -e INSTALLATION_MODE="container" ${YARDSTICK_REPO_DIR}/ansible/install.yaml
+RUN ansible-playbook -i ${YARDSTICK_REPO_DIR}/ansible/install-inventory.ini -c local -vvv -e INSTALLATION_MODE="container" ${YARDSTICK_REPO_DIR}/ansible/install.yaml
 
 RUN ${YARDSTICK_REPO_DIR}/docker/supervisor.sh
 
index 21095cb..ef41cba 100644 (file)
@@ -31,7 +31,7 @@ index 62ea0d0..f2f41771 100644
 +RUN apt-get update && apt-get install -y git python python-setuptools python-pip iputils-ping && apt-get -y autoremove && \
 +    apt-get install -y libssl-dev && apt-get -y install libffi-dev && apt-get clean
  RUN easy_install -U setuptools==30.0.0
- RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 python-openstackclient==3.11.0 python-heatclient==1.11.0 ansible==2.4.2
+ RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 python-openstackclient==3.12.0 python-heatclient==1.11.0 ansible==2.5.5
 
 @@ -48,8 +49,8 @@ RUN echo "daemon off;" >> /etc/nginx/nginx.conf
  # nginx=5000, rabbitmq=5672
index 7ea2616..daa4b81 100644 (file)
@@ -36,6 +36,12 @@ Version History
 | *Date*            | *Version* | *Comment*                       |
 |                   |           |                                 |
 +-------------------+-----------+---------------------------------+
+| Jul 2, 2018       | 6.2.1     | Yardstick for Fraser release    |
+|                   |           |                                 |
++-------------------+-----------+---------------------------------+
+| Jun 29, 2018      | 6.2.0     | Yardstick for Fraser release    |
+|                   |           |                                 |
++-------------------+-----------+---------------------------------+
 | May 25, 2018      | 6.1.0     | Yardstick for Fraser release    |
 |                   |           |                                 |
 +-------------------+-----------+---------------------------------+
@@ -120,19 +126,19 @@ Release Data
 | **Project**                    | Yardstick             |
 |                                |                       |
 +--------------------------------+-----------------------+
-| **Repo/tag**                   | yardstick/opnfv-6.1.0 |
+| **Repo/tag**                   | yardstick/opnfv-6.2.0 |
 |                                |                       |
 +--------------------------------+-----------------------+
-| **Yardstick Docker image tag** | opnfv-6.1.0           |
+| **Yardstick Docker image tag** | opnfv-6.2.0           |
 |                                |                       |
 +--------------------------------+-----------------------+
 | **Release designation**        | Fraser                |
 |                                |                       |
 +--------------------------------+-----------------------+
-| **Release date**               | May 25, 2018          |
+| **Release date**               | Jun 29, 2018          |
 |                                |                       |
 +--------------------------------+-----------------------+
-| **Purpose of the delivery**    | OPNFV Fraser 6.1.0    |
+| **Purpose of the delivery**    | OPNFV Fraser 6.2.0    |
 |                                |                       |
 +--------------------------------+-----------------------+
 
@@ -151,7 +157,7 @@ Documents
 Software Deliverables
 ---------------------
 
- - The Yardstick Docker image: https://hub.docker.com/r/opnfv/yardstick (tag: opnfv-6.1.0)
+ - The Yardstick Docker image: https://hub.docker.com/r/opnfv/yardstick (tag: opnfv-6.2.0)
 
 List of Contexts
 ^^^^^^^^^^^^^^^^
@@ -391,6 +397,110 @@ Known Issues/Faults
 Corrected Faults
 ----------------
 
+Fraser 6.2.1:
+
++--------------------+--------------------------------------------------------------------------+
+| **JIRA REFERENCE** |                             **DESCRIPTION**                              |
++====================+==========================================================================+
+|   YARDSTICK-1147   | Fix ansible scripts for running in container                             |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1157   | Bug Fix: correct the file path to build docker file                      |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1276   | Bugfix: docker build failed                                              |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1280   | Bugfix: uwsgi config file yardstick.ini output error                     |
++--------------------+--------------------------------------------------------------------------+
+
+Fraser 6.2.0:
+
++--------------------+--------------------------------------------------------------------------+
+| **JIRA REFERENCE** |                             **DESCRIPTION**                              |
++====================+==========================================================================+
+|   YARDSTICK-1246   | Update pmd/lcore mask for OVS-DPDK context                               |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-837    | Move tests: unit/network_services/{lib/,collector/,*.py}                 |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1144   | Correctly set PYTHONPATH in Dockerfile                                   |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1205   | Set "cmd2" library to version 0.8.6                                      |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1204   | Bump oslo.messaging version to 5.36.0                                    |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1210   | Remove __init__ method overriding in HeatContextTestCase                 |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1189   | Error when adding SR-IOV interfaces in SR-IOV context                    |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1214   | Remove AnsibleCommon class method mock                                   |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1159   | Add --hwlb options as a command line argument for SampleVNF              |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1203   | Add scale out TCs with availability zone support                         |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1167   | Do not start collectd twice when SampleVNF is running on Baremetal       |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1188   | Add "host_name_separator" variable to Context class                      |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1112   | MQ startup process refactor                                              |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1229   | Cleanup BaseMonitor unit tests                                           |
++--------------------+--------------------------------------------------------------------------+
+|         -          | Configure ACL via static file                                            |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1191   | Use TRex release v2.41 to support both x86 and aarch64                   |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1106   | Add IxNetwork API Python Binding package                                 |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1224   | Cleanup TestYardstickNSCli class                                         |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1225   | Remove print out of logger exception in TestUtils                        |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1194   | Add "duration" parameter to test case definition                         |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1209   | Remove instantiated contexts in "test_task"                              |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1192   | Standalone XML machine type is not longer valid                          |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1197   | Refactor RFC2455 TRex traffic profile injection                          |
++--------------------+--------------------------------------------------------------------------+
+|         -          | Fix "os.path" mock problems during tests                                 |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1218   | Refactor "utils.parse_ini_file" testing                                  |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1179   | Start nginx and uwsgi servicies only in not container mode               |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1177   | Install dependencies: bare-metal, standalone                             |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1126   | Migrate install.sh script to ansible                                     |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1146   | Fix nsb_setup.sh script                                                  |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1247   | NSB setup inventory name changed                                         |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1116   | Changed IxNextgen library load in IXIA RFC2544 traffic generator call.   |
++--------------------+--------------------------------------------------------------------------+
+|         -          | Corrected scale-up command line arguments                                |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-878    | OpenStack client replacement                                             |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1222   | Bugfix: HA kill process recovery has a conflict                          |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1139   | Add "os_cloud_config" as a new context flag parameter                    |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1255   | Extended Context class with get_physical_nodes functionality             |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1244   | NSB NFVi BNG test fails to run - stops after one step                    |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1219   | Decrease Sampling interval                                               |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1101   | NSB NFVi PROX BNG losing many packets                                    |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1217   | Fix NSB NfVi support for 25 and 40Gbps                                   |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-1185   | NSB Topology fix for Prox 4 port test case                               |
++--------------------+--------------------------------------------------------------------------+
+|   YARDSTICK-966    | Convert SLA asserts to raises                                            |
++--------------------+--------------------------------------------------------------------------+
+
 Fraser 6.1.0:
 
 +--------------------+--------------------------------------------------------------------------+
diff --git a/docs/release/results/euphrates_fraser_comparison.rst b/docs/release/results/euphrates_fraser_comparison.rst
new file mode 100644 (file)
index 0000000..53dfb99
--- /dev/null
@@ -0,0 +1,602 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International
+.. License.
+.. http://creativecommons.org/licenses/by/4.0
+
+=======================================================
+Test results analysis for Euphrates and Fraser releases
+=======================================================
+
+TC002
+-----
+
+The round-trip-time (RTT) between 2 VMs on different blades is measured using
+ping.
+
+Most test run measurements result on average between 0.39 and 4.00 ms.
+Compared with Euphrates release, the average RTT result of the same pod experiences
+a slight decline in Fraser release. For example, the average RTT of arm-pod5 is
+1.518 in Ehphrates and 1.714 in Fraser. The average RTT of intel-pod18 is 1.6575
+ms in Ehphrates and 1.856 ms in Fraser.
+
+{
+
+    "huawei-pod2:stable/euphrates": [0.3925],
+
+    "lf-pod2:stable/euphrates": [0.5315],
+
+    "lf-pod1:stable/euphrates": [0.62],
+
+    "huawei-pod2:stable/fraser": [0.677],
+
+    "lf-pod1:stable/fraser": [0.725],
+
+    "flex-pod2:stable/euphrates": [0.795],
+
+    "huawei-pod12:stable/euphrates": [0.87],
+
+    "ericsson-pod1:stable/fraser": [0.9165],
+
+    "huawei-pod12:stable/fraser": [1.0465],
+
+    "lf-pod2:stable/fraser": [1.2325],
+
+    "intel-pod5:stable/euphrates": [1.25],
+
+    "ericsson-virtual3:stable/euphrates": [1.2655],
+
+    "ericsson-pod1:stable/euphrates": [1.372],
+
+    "zte-pod2:stable/fraser": [1.395],
+
+    "arm-pod5:stable/euphrates": [1.518],
+
+    "huawei-virtual4:stable/euphrates": [1.5355],
+
+    "ericsson-virtual4:stable/fraser": [1.582],
+
+    "huawei-virtual3:stable/euphrates": [1.606],
+
+    "intel-pod18:stable/euphrates": [1.6575],
+
+    "huawei-virtual4:stable/fraser": [1.697],
+
+    "huawei-virtual8:stable/euphrates": [1.709],
+
+    "arm-pod5:stable/fraser": [1.714],
+
+    "huawei-virtual3:stable/fraser": [1.716],
+
+    "intel-pod18:stable/fraser": [1.856],
+
+    "huawei-virtual2:stable/euphrates": [1.872],
+
+    "arm-pod6:stable/euphrates": [1.895],
+
+    "huawei-virtual2:stable/fraser": [1.964],
+
+    "huawei-virtual1:stable/fraser": [1.9765],
+
+    "huawei-virtual9:stable/euphrates": [2.0745],
+
+    "arm-pod6:stable/fraser": [2.209],
+
+    "huawei-virtual1:stable/euphrates": [2.495],
+
+    "ericsson-virtual2:stable/euphrates": [2.7895],
+
+    "ericsson-virtual4:stable/euphrates": [3.768],
+
+    "ericsson-virtual1:stable/euphrates": [3.8035],
+
+    "ericsson-virtual3:stable/fraser": [3.9175],
+
+    "ericsson-virtual2:stable/fraser": [4.004]
+
+}
+
+TC010
+-----
+
+The tool we use to measure memory read latency is lmbench, which is a series of
+micro benchmarks intended to measure basic operating system and hardware system
+metrics. Compared with Euphrates release, the memory read latency of the same pod
+also experience a slight decline. Virtual pods seem to have a higher memory read
+latency than physical pods. Compared with X86 pods, the memory read latency of
+arm pods is significant higher.
+
+{
+
+    "ericsson-pod1:stable/euphrates": [5.7785],
+
+    "flex-pod2:stable/euphrates": [5.908],
+
+    "ericsson-virtual1:stable/euphrates": [6.412],
+
+    "intel-pod18:stable/euphrates": [6.5905],
+
+    "intel-pod5:stable/euphrates": [6.6975],
+
+    "ericsson-pod1:stable/fraser": [7.0645],
+
+    "ericsson-virtual4:stable/euphrates": [7.183],
+
+    "intel-pod18:stable/fraser": [7.4465],
+
+    "zte-pod2:stable/fraser": [8.1865],
+
+    "ericsson-virtual2:stable/euphrates": [8.4985],
+
+    "huawei-pod2:stable/euphrates": [8.877],
+
+    "huawei-pod12:stable/euphrates": [9.091],
+
+    "huawei-pod2:stable/fraser": [9.236],
+
+    "huawei-pod12:stable/fraser": [9.615],
+
+    "ericsson-virtual3:stable/euphrates": [9.719],
+
+    "ericsson-virtual2:stable/fraser": [9.8925],
+
+    "huawei-virtual4:stable/euphrates": [10.1195],
+
+    "huawei-virtual3:stable/euphrates": [10.19],
+
+    "huawei-virtual2:stable/fraser": [10.22],
+
+    "huawei-virtual1:stable/euphrates": [10.3045],
+
+    "huawei-virtual9:stable/euphrates": [10.318],
+
+    "ericsson-virtual4:stable/fraser": [10.5465],
+
+    "ericsson-virtual3:stable/fraser": [10.9355],
+
+    "huawei-virtual3:stable/fraser": [10.95],
+
+    "huawei-virtual2:stable/euphrates": [11.274],
+
+    "huawei-virtual4:stable/fraser": [11.557],
+
+    "lf-pod1:stable/euphrates": [15.7025],
+
+    "lf-pod2:stable/euphrates": [15.8495],
+
+    "lf-pod2:stable/fraser": [16.5595],
+
+    "lf-pod1:stable/fraser": [16.8395],
+
+    "arm-pod5:stable/euphrates": [18.092],
+
+    "arm-pod5:stable/fraser": [18.744],
+
+    "huawei-virtual1:stable/fraser": [19.8235],
+
+    "huawei-virtual8:stable/euphrates": [33.999],
+
+    "arm-pod6:stable/euphrates": [41.5605],
+
+    "arm-pod6:stable/fraser": [55.804]
+
+}
+
+TC011
+-----
+
+Iperf3 is a tool for evaluating the packet delay variation between 2 VMs on
+different blades. In general, the packet delay variation of the two releases
+look similar.
+
+{
+
+    "arm-pod6:stable/fraser": [1],
+
+    "ericsson-pod1:stable/fraser": [1],
+
+    "ericsson-virtual2:stable/fraser": [1],
+
+    "ericsson-virtual3:stable/fraser": [1],
+
+    "lf-pod2:stable/fraser": [1],
+
+    "huawei-virtual1:stable/fraser": [2997],
+
+    "huawei-virtual2:stable/euphrates": [2997],
+
+    "flex-pod2:stable/euphrates": [2997.5],
+
+    "huawei-virtual3:stable/euphrates": [2998],
+
+    "huawei-virtual3:stable/fraser": [2999],
+
+    "huawei-virtual9:stable/euphrates": [3000],
+
+    "huawei-virtual8:stable/euphrates": [3001],
+
+    "huawei-virtual4:stable/euphrates": [3002],
+
+    "huawei-virtual4:stable/fraser": [3002],
+
+    "ericsson-virtual3:stable/euphrates": [3006],
+
+    "huawei-virtual1:stable/euphrates": [3007],
+
+    "ericsson-virtual2:stable/euphrates": [3009],
+
+    "intel-pod18:stable/euphrates": [3010],
+
+    "ericsson-virtual4:stable/euphrates": [3017],
+
+    "lf-pod2:stable/euphrates": [3021],
+
+    "arm-pod5:stable/euphrates": [3022],
+
+    "arm-pod6:stable/euphrates": [3022],
+
+    "ericsson-pod1:stable/euphrates": [3022],
+
+    "huawei-pod12:stable/euphrates": [3022],
+
+    "huawei-pod12:stable/fraser": [3022],
+
+    "huawei-pod2:stable/euphrates": [3022],
+
+    "huawei-pod2:stable/fraser": [3022],
+
+    "intel-pod18:stable/fraser": [3022],
+
+    "intel-pod5:stable/euphrates": [3022],
+
+    "lf-pod1:stable/euphrates": [3022],
+
+    "lf-pod1:stable/fraser": [3022],
+
+    "zte-pod2:stable/fraser": [3022],
+
+    "huawei-virtual2:stable/fraser": [3025]
+
+}
+
+TC012
+-----
+
+Lmbench is also used to measure the memory read and write bandwidth.
+Like TC010, compared with Euphrates release, the memory read and write bandwidth
+of the same pod also experience a slight decline. And compared with X86 pods, the memory
+read and write bandwidth of arm pods is significant lower.
+
+{
+
+    "lf-pod1:stable/euphrates": [22912.39],
+
+    "lf-pod2:stable/euphrates": [22637.67],
+
+    "lf-pod1:stable/fraser": [20552.9],
+
+    "flex-pod2:stable/euphrates": [20229.99],
+
+    "lf-pod2:stable/fraser": [20058.925],
+
+    "ericsson-pod1:stable/fraser": [18930.78],
+
+    "intel-pod18:stable/fraser": [18757.545],
+
+    "ericsson-virtual1:stable/euphrates": [17474.965],
+
+    "ericsson-pod1:stable/euphrates": [17127.38],
+
+    "ericsson-virtual4:stable/euphrates": [16219.97],
+
+    "ericsson-virtual2:stable/euphrates": [15652.28],
+
+    "ericsson-virtual3:stable/euphrates": [15551.26],
+
+    "ericsson-virtual4:stable/fraser": [15389.465],
+
+    "ericsson-virtual2:stable/fraser": [15343.79],
+
+    "huawei-pod2:stable/euphrates": [15017.2],
+
+    "huawei-pod2:stable/fraser": [14870.78],
+
+    "huawei-virtual4:stable/euphrates": [14266.34],
+
+    "huawei-virtual1:stable/euphrates": [14233.035],
+
+    "huawei-virtual3:stable/euphrates": [14227.63],
+
+    "zte-pod2:stable/fraser": [14157.99],
+
+    "huawei-pod12:stable/euphrates": [14147.245],
+
+    "huawei-pod12:stable/fraser": [14126.99],
+
+    "intel-pod18:stable/euphrates": [14058.33],
+
+    "huawei-virtual3:stable/fraser": [13929.67],
+
+    "huawei-virtual2:stable/euphrates": [13862.85],
+
+    "huawei-virtual4:stable/fraser": [13847.155],
+
+    "huawei-virtual2:stable/fraser": [13702.92],
+
+    "huawei-virtual1:stable/fraser": [13496.45],
+
+    "intel-pod5:stable/euphrates": [13280.32],
+
+    "ericsson-virtual3:stable/fraser": [12733.19],
+
+    "huawei-virtual9:stable/euphrates": [12559.445],
+
+    "huawei-virtual8:stable/euphrates": [8998.02],
+
+    "arm-pod5:stable/euphrates": [4388.875],
+
+    "arm-pod5:stable/fraser": [4326.11],
+
+    "arm-pod6:stable/euphrates": [4260.2],
+
+    "arm-pod6:stable/fraser": [3809.885]
+
+}
+
+TC014
+-----
+
+The Unixbench is used to evaluate the IaaS processing speed with regards to
+score of single CPU running and parallel running. Below are the single CPU running
+scores. It can be seen that the processing test results vary from scores 715 to 3737.
+In general, the single CPU score of the two releases look similar.
+
+{
+
+    "lf-pod2:stable/fraser": [3737.6],
+
+    "lf-pod2:stable/euphrates": [3723.95],
+
+    "lf-pod1:stable/fraser": [3702.7],
+
+    "lf-pod1:stable/euphrates": [3669],
+
+    "intel-pod5:stable/euphrates": [3388.6],
+
+    "intel-pod18:stable/euphrates": [3298.4],
+
+    "flex-pod2:stable/euphrates": [3208.6],
+
+    "ericsson-pod1:stable/fraser": [3131.6],
+
+    "intel-pod18:stable/fraser": [3098.1],
+
+    "ericsson-virtual1:stable/euphrates": [2988.9],
+
+    "zte-pod2:stable/fraser": [2831.4],
+
+    "ericsson-pod1:stable/euphrates": [2669.1],
+
+    "ericsson-virtual4:stable/euphrates": [2598.5],
+
+    "ericsson-virtual2:stable/fraser": [2559.7],
+
+    "ericsson-virtual3:stable/euphrates": [2553.15],
+
+    "huawei-pod2:stable/euphrates": [2531.2],
+
+    "huawei-pod2:stable/fraser": [2528.9],
+
+    "ericsson-virtual4:stable/fraser": [2527.8],
+
+    "ericsson-virtual2:stable/euphrates": [2526.9],
+
+    "huawei-virtual4:stable/euphrates": [2407.4],
+
+    "huawei-virtual3:stable/fraser": [2379.1],
+
+    "huawei-virtual3:stable/euphrates": [2374.6],
+
+    "huawei-virtual4:stable/fraser": [2362.1],
+
+    "huawei-virtual2:stable/euphrates": [2326.4],
+
+    "huawei-virtual9:stable/euphrates": [2324.95],
+
+    "huawei-virtual1:stable/euphrates": [2302.6],
+
+    "huawei-virtual2:stable/fraser": [2299.3],
+
+    "huawei-pod12:stable/euphrates": [2232.2],
+
+    "huawei-pod12:stable/fraser": [2229],
+
+    "huawei-virtual1:stable/fraser": [2171.3],
+
+    "ericsson-virtual3:stable/fraser": [2104.8],
+
+    "huawei-virtual8:stable/euphrates": [2085.3],
+
+    "arm-pod5:stable/fraser": [1764.2],
+
+    "arm-pod5:stable/euphrates": [1754.4],
+
+    "arm-pod6:stable/euphrates": [716.15],
+
+    "arm-pod6:stable/fraser": [715.4]
+
+}
+
+TC069
+-----
+
+With the block size changing from 1 kb to 512 kb, the memory write bandwidth
+tends to become larger first and then smaller within every run test. Below are
+the scores for 32mb block array.
+
+{
+
+    "intel-pod18:stable/euphrates": [18871.79],
+
+    "intel-pod18:stable/fraser": [16939.24],
+
+    "intel-pod5:stable/euphrates": [16055.79],
+
+    "arm-pod6:stable/euphrates": [13327.02],
+
+    "arm-pod6:stable/fraser": [11895.71],
+
+    "flex-pod2:stable/euphrates": [9384.585],
+
+    "zte-pod2:stable/fraser": [9375.33],
+
+    "ericsson-pod1:stable/euphrates": [9331.535],
+
+    "huawei-pod12:stable/euphrates": [9164.88],
+
+    "ericsson-pod1:stable/fraser": [9140.42],
+
+    "huawei-pod2:stable/euphrates": [9026.52],
+
+    "huawei-pod12:stable/fraser": [8993.37],
+
+    "huawei-virtual9:stable/euphrates": [8825.805],
+
+    "huawei-pod2:stable/fraser": [8794.01],
+
+    "huawei-virtual2:stable/fraser": [7670.21],
+
+    "ericsson-virtual1:stable/euphrates": [7615.97],
+
+    "ericsson-virtual4:stable/euphrates": [7539.23],
+
+    "arm-pod5:stable/fraser": [7479.32],
+
+    "arm-pod5:stable/euphrates": [7403.38],
+
+    "huawei-virtual3:stable/euphrates": [7247.89],
+
+    "ericsson-virtual2:stable/fraser": [7219.21],
+
+    "huawei-virtual2:stable/euphrates": [7205.35],
+
+    "huawei-virtual1:stable/euphrates": [7196.405],
+
+    "ericsson-virtual3:stable/euphrates": [7173.72],
+
+    "huawei-virtual4:stable/euphrates": [7131.47],
+
+    "ericsson-virtual2:stable/euphrates": [7129.08],
+
+    "huawei-virtual4:stable/fraser": [7059.045],
+
+    "huawei-virtual3:stable/fraser": [7023.57],
+
+    "lf-pod1:stable/euphrates": [6928.18],
+
+    "lf-pod2:stable/euphrates": [6875.88],
+
+    "lf-pod2:stable/fraser": [6834.7],
+
+    "lf-pod1:stable/fraser": [6775.27],
+
+    "ericsson-virtual4:stable/fraser": [6522.86],
+
+    "ericsson-virtual3:stable/fraser": [5835.59],
+
+    "huawei-virtual8:stable/euphrates": [5729.705],
+
+    "huawei-virtual1:stable/fraser": [5617.12]
+
+}
+
+TC082
+-----
+
+For this test case, we use perf to measure context-switches under load.
+High context switch rates are not themselves an issue, but they may point the
+way to a more significant problem.
+
+{
+
+    "zte-pod2:stable/fraser": [306.5],
+
+    "huawei-pod12:stable/euphrates": [316],
+
+    "lf-pod2:stable/fraser": [337.5],
+
+    "intel-pod18:stable/euphrates": [340],
+
+    "intel-pod18:stable/fraser": [343.5],
+
+    "intel-pod5:stable/euphrates": [357.5],
+
+    "ericsson-pod1:stable/euphrates": [384],
+
+    "lf-pod2:stable/euphrates": [394.5],
+
+    "huawei-pod12:stable/fraser": [399],
+
+    "lf-pod1:stable/euphrates": [435],
+
+    "lf-pod1:stable/fraser": [454],
+
+    "flex-pod2:stable/euphrates": [476],
+
+    "huawei-pod2:stable/euphrates": [518],
+
+    "huawei-pod2:stable/fraser": [544.5],
+
+    "arm-pod5:stable/euphrates": [869.5],
+
+    "huawei-virtual9:stable/euphrates": [1002],
+
+    "huawei-virtual4:stable/fraser": [1138],
+
+    "huawei-virtual4:stable/euphrates": [1174],
+
+    "huawei-virtual3:stable/euphrates": [1239],
+
+    "ericsson-pod1:stable/fraser": [1305],
+
+    "huawei-virtual2:stable/euphrates": [1430],
+
+    "huawei-virtual3:stable/fraser": [1433],
+
+    "huawei-virtual1:stable/fraser": [1470],
+
+    "huawei-virtual1:stable/euphrates": [1489],
+
+    "arm-pod6:stable/fraser": [1738.5],
+
+    "arm-pod6:stable/euphrates": [1883.5]
+
+}
+
+TC083
+-----
+
+TC083 measures network latency and throughput between VMs using netperf.
+The test results shown below are for UDP throughout.
+
+{
+
+    "lf-pod1:stable/euphrates": [2204.42],
+
+    "lf-pod2:stable/fraser": [1893.39],
+
+    "intel-pod18:stable/euphrates": [1835.55],
+
+    "lf-pod2:stable/euphrates": [1676.705],
+
+    "intel-pod5:stable/euphrates": [1612.555],
+
+    "zte-pod2:stable/fraser": [1543.995],
+
+    "lf-pod1:stable/fraser": [1480.86],
+
+    "intel-pod18:stable/fraser": [1417.015],
+
+    "flex-pod2:stable/euphrates": [1370.23],
+
+    "huawei-pod12:stable/euphrates": [1300.12]
+
+}
diff --git a/docs/release/results/euphrates_fraser_comparsion.rst b/docs/release/results/euphrates_fraser_comparsion.rst
deleted file mode 100644 (file)
index 222dc8b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-.. This work is licensed under a Creative Commons Attribution 4.0 International
-.. License.
-.. http://creativecommons.org/licenses/by/4.0
-
-=======================================================
-Test results analysis for Euphrates and Fraser releases
-=======================================================
-
diff --git a/docs/release/results/images/tc002_pod_fraser.png b/docs/release/results/images/tc002_pod_fraser.png
new file mode 100644 (file)
index 0000000..797dc31
Binary files /dev/null and b/docs/release/results/images/tc002_pod_fraser.png differ
diff --git a/docs/release/results/images/tc002_scenario_fraser.png b/docs/release/results/images/tc002_scenario_fraser.png
new file mode 100644 (file)
index 0000000..ff42e65
Binary files /dev/null and b/docs/release/results/images/tc002_scenario_fraser.png differ
diff --git a/docs/release/results/images/tc010_pod_fraser.png b/docs/release/results/images/tc010_pod_fraser.png
new file mode 100644 (file)
index 0000000..23367d3
Binary files /dev/null and b/docs/release/results/images/tc010_pod_fraser.png differ
diff --git a/docs/release/results/images/tc010_scenario_fraser.png b/docs/release/results/images/tc010_scenario_fraser.png
new file mode 100644 (file)
index 0000000..a481a59
Binary files /dev/null and b/docs/release/results/images/tc010_scenario_fraser.png differ
diff --git a/docs/release/results/images/tc011_pod_fraser.png b/docs/release/results/images/tc011_pod_fraser.png
new file mode 100644 (file)
index 0000000..82dc9c7
Binary files /dev/null and b/docs/release/results/images/tc011_pod_fraser.png differ
diff --git a/docs/release/results/images/tc011_scenario_fraser.png b/docs/release/results/images/tc011_scenario_fraser.png
new file mode 100644 (file)
index 0000000..226d0b8
Binary files /dev/null and b/docs/release/results/images/tc011_scenario_fraser.png differ
diff --git a/docs/release/results/images/tc012_pod_fraser.png b/docs/release/results/images/tc012_pod_fraser.png
new file mode 100644 (file)
index 0000000..66e79be
Binary files /dev/null and b/docs/release/results/images/tc012_pod_fraser.png differ
diff --git a/docs/release/results/images/tc012_scenario_fraser.png b/docs/release/results/images/tc012_scenario_fraser.png
new file mode 100644 (file)
index 0000000..4ef4411
Binary files /dev/null and b/docs/release/results/images/tc012_scenario_fraser.png differ
diff --git a/docs/release/results/images/tc014_pod_fraseer.png b/docs/release/results/images/tc014_pod_fraseer.png
new file mode 100644 (file)
index 0000000..697201d
Binary files /dev/null and b/docs/release/results/images/tc014_pod_fraseer.png differ
diff --git a/docs/release/results/images/tc014_scenario_fraser.png b/docs/release/results/images/tc014_scenario_fraser.png
new file mode 100644 (file)
index 0000000..f7865dc
Binary files /dev/null and b/docs/release/results/images/tc014_scenario_fraser.png differ
diff --git a/docs/release/results/images/tc069_pod_fraser.png b/docs/release/results/images/tc069_pod_fraser.png
new file mode 100644 (file)
index 0000000..1cba192
Binary files /dev/null and b/docs/release/results/images/tc069_pod_fraser.png differ
diff --git a/docs/release/results/images/tc069_scenario_fraser.png b/docs/release/results/images/tc069_scenario_fraser.png
new file mode 100644 (file)
index 0000000..f988b90
Binary files /dev/null and b/docs/release/results/images/tc069_scenario_fraser.png differ
diff --git a/docs/release/results/images/tc082_pod_fraser.png b/docs/release/results/images/tc082_pod_fraser.png
new file mode 100644 (file)
index 0000000..d54ab90
Binary files /dev/null and b/docs/release/results/images/tc082_pod_fraser.png differ
diff --git a/docs/release/results/images/tc083_pod_fraser.png b/docs/release/results/images/tc083_pod_fraser.png
new file mode 100644 (file)
index 0000000..942cc20
Binary files /dev/null and b/docs/release/results/images/tc083_pod_fraser.png differ
index 3ec9e1c..63445fd 100644 (file)
@@ -14,4 +14,4 @@ Yardstick test results
 
 .. include:: ./overview.rst
 .. include:: ./results.rst
-.. include:: ./euphrates_fraser_comparsion.rst
+.. include:: ./euphrates_fraser_comparison.rst
index c75f5ae..0ed92f8 100644 (file)
@@ -23,6 +23,7 @@ Scenario Results
 The following documents contain results of Yardstick test cases executed on
 OPNFV labs, triggered by OPNFV CI pipeline, documented per test case.
 
+For hardware details of OPNFV labs, please visit: https://wiki.opnfv.org/display/pharos/Community+Labs
 
 .. toctree::
    :maxdepth: 1
@@ -38,6 +39,7 @@ OPNFV labs, triggered by OPNFV CI pipeline, documented per test case.
 
 Test results of executed tests are avilable in Dashboard_ and logs in Jenkins_.
 
+Test results for Fraser release are collected from April 10, 2018 to May 13, 2018.
 
 Feature Test Results
 ====================
index 7224234..064983b 100644 (file)
@@ -315,3 +315,211 @@ The influence of the POD
 
 Fraser release
 --------------
+
+Test results per scenario and pod (lower is better):
+
+{
+
+    "os-odl_l3-nofeature-ha:huawei-pod2:compass": [0.42],
+
+    "os-odl-sfc-ha:huawei-pod2:compass": [0.557],
+
+    "os-nosdn-ovs-ha:ericsson-pod1:fuel": [0.5765],
+
+    "os-nosdn-kvm-ha:huawei-pod2:compass": [0.582],
+
+    "os-odl-bgpvpn-ha:lf-pod1:apex": [0.678],
+
+    "os-nosdn-nofeature-ha:lf-pod1:apex": [0.7075],
+
+    "os-nosdn-calipso-noha:lf-pod1:apex": [0.713],
+
+    "os-nosdn-nofeature-noha:lf-pod1:apex": [0.7155],
+
+    "os-nosdn-bar-ha:lf-pod1:apex": [0.732],
+
+    "os-nosdn-bar-noha:lf-pod1:apex": [0.7415],
+
+    "os-odl-nofeature-noha:lf-pod1:apex": [0.7565],
+
+    "os-nosdn-ovs-ha:arm-pod6:fuel": [0.8015],
+
+    "os-nosdn-nofeature-ha:huawei-pod2:compass": [0.908],
+
+    "os-odl-nofeature-ha:ericsson-pod1:fuel": [0.9165],
+
+    "os-nosdn-bar-ha:huawei-pod2:compass": [0.969],
+
+    "os-nosdn-ovs-noha:ericsson-virtual2:fuel": [0.9765],
+
+    "os-nosdn-nofeature-noha:huawei-pod12:joid": [1.0245],
+
+    "os-nosdn-nofeature-ha:huawei-pod12:joid": [1.0495],
+
+    "os-odl-sfc-noha:huawei-virtual4:compass": [1.1645],
+
+    "os-nosdn-nofeature-ha:lf-pod2:fuel": [1.206],
+
+    "os-odl-sfc-noha:huawei-virtual3:compass": [1.236],
+
+    "os-nosdn-ovs-noha:ericsson-virtual4:fuel": [1.241],
+
+    "os-nosdn-nofeature-ha:zte-pod2:daisy": [1.2805],
+
+    "os-odl-nofeature-ha:lf-pod2:fuel": [1.286],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual3:compass": [1.299],
+
+    "os-odl-sfc-ha:huawei-virtual4:compass": [1.305],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual4:compass": [1.309],
+
+    "os-nosdn-kvm-noha:huawei-virtual4:compass": [1.314],
+
+    "os-nosdn-nofeature-noha:huawei-virtual4:compass": [1.431],
+
+    "os-nosdn-nofeature-ha:ericsson-pod1:fuel": [1.457],
+
+    "os-odl-nofeature-ha:zte-pod2:daisy": [1.517],
+
+    "os-nosdn-kvm-noha:huawei-virtual3:compass": [1.576],
+
+    "os-nosdn-nofeature-noha:huawei-virtual3:compass": [1.592],
+
+    "os-odl-nofeature-ha:arm-pod5:fuel": [1.714],
+
+    "os-nosdn-nofeature-noha:intel-pod18:joid": [1.809],
+
+    "os-nosdn-bar-noha:huawei-virtual4:compass": [1.81],
+
+    "os-nosdn-nofeature-ha:intel-pod18:joid": [1.8505],
+
+    "os-nosdn-nofeature-ha:huawei-virtual4:compass": [1.8895],
+
+    "os-nosdn-nofeature-ha:huawei-virtual3:compass": [1.909],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual4:compass": [1.925],
+
+    "os-nosdn-nofeature-noha:huawei-virtual2:compass": [1.964],
+
+    "os-nosdn-openbaton-ha:intel-pod18:joid": [1.9755],
+
+    "os-nosdn-nofeature-ha:huawei-virtual1:compass": [1.9765],
+
+    "os-nosdn-bar-noha:huawei-virtual3:compass": [1.9915],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual3:compass": [1.9925],
+
+    "os-nosdn-kvm-ha:huawei-virtual4:compass": [2.0265],
+
+    "os-odl-nofeature-ha:arm-pod6:fuel": [2.106],
+
+    "os-odl-sfc-ha:huawei-virtual3:compass": [2.124],
+
+    "os-nosdn-kvm-ha:huawei-virtual3:compass": [2.185],
+
+    "os-nosdn-nofeature-ha:arm-pod6:fuel": [2.281],
+
+    "os-nosdn-bar-ha:huawei-virtual4:compass": [2.432],
+
+    "os-odl-nofeature-noha:ericsson-virtual4:fuel": [2.483],
+
+    "os-nosdn-bar-ha:huawei-virtual3:compass": [2.524],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual3:fuel": [3.9175],
+
+    "os-odl-nofeature-noha:ericsson-virtual2:fuel": [4.338],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual2:fuel": [4.641]
+
+}
+
+
+The influence of the scenario
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc002_scenario_fraser.png
+   :width: 800px
+   :alt: TC002 influence of scenario
+
+{
+
+    "os-odl-bgpvpn-ha": [0.678],
+
+    "os-nosdn-calipso-noha": [0.713],
+
+    "os-nosdn-ovs-ha": [0.7245],
+
+    "os-odl_l3-nofeature-ha": [0.7435],
+
+    "os-odl-sfc-ha": [0.796],
+
+    "os-nosdn-kvm-ha": [1.059],
+
+    "os-nosdn-bar-ha": [1.083],
+
+    "os-nosdn-ovs-noha": [1.09],
+
+    "os-odl-sfc-noha": [1.196],
+
+    "os-nosdn-nofeature-noha": [1.26],
+
+    "os-nosdn-nofeature-ha": [1.291],
+
+    "os-odl_l3-nofeature-noha": [1.308],
+
+    "os-nosdn-bar-noha": [1.4125],
+
+    "os-nosdn-kvm-noha": [1.4475],
+
+    "os-odl-nofeature-ha": [1.508],
+
+    "os-odl-nofeature-noha": [1.914],
+
+    "os-nosdn-openbaton-ha": [1.9755]
+
+}
+
+
+The influence of the POD
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc002_pod_fraser.png
+   :width: 800px
+   :alt: TC002 influence of the POD
+
+{
+
+    "huawei-pod2": [0.677],
+
+    "lf-pod1": [0.725],
+
+    "ericsson-pod1": [0.9165],
+
+    "huawei-pod12": [1.0465],
+
+    "lf-pod2": [1.2325],
+
+    "zte-pod2": [1.395],
+
+    "ericsson-virtual4": [1.582],
+
+    "huawei-virtual4": [1.697],
+
+    "arm-pod5": [1.714],
+
+    "huawei-virtual3": [1.716],
+
+    "intel-pod18": [1.856],
+
+    "huawei-virtual2": [1.964],
+
+    "huawei-virtual1": [1.9765],
+
+    "arm-pod6": [2.209],
+
+    "ericsson-virtual3": [3.9175],
+
+    "ericsson-virtual2": [4.004]
+
+}
index 9a296b7..81559d6 100644 (file)
@@ -297,3 +297,214 @@ The influence of the POD
 
 Fraser release
 --------------
+
+Test results per scenario and pod (lower is better):
+
+{
+
+    "os-odl-nofeature-ha:ericsson-pod1:fuel": [6.8675],
+
+    "os-nosdn-nofeature-noha:intel-pod18:joid": [6.991],
+
+    "os-nosdn-openbaton-ha:intel-pod18:joid": [7.5535],
+
+    "os-nosdn-nofeature-ha:intel-pod18:joid": [7.571],
+    "os-nosdn-ovs-ha:ericsson-pod1:fuel": [7.635],
+
+    "os-nosdn-nofeature-ha:zte-pod2:daisy": [8.153],
+
+    "os-odl-nofeature-ha:zte-pod2:daisy": [8.1935],
+
+    "os-nosdn-bar-ha:huawei-pod2:compass": [9.1715],
+
+    "os-odl-sfc-ha:huawei-pod2:compass": [9.1875],
+
+    "os-odl_l3-nofeature-ha:huawei-pod2:compass": [9.241],
+
+    "os-nosdn-nofeature-ha:huawei-pod2:compass": [9.255],
+
+    "os-nosdn-kvm-ha:huawei-pod2:compass": [9.388],
+
+    "os-nosdn-nofeature-noha:huawei-virtual4:compass": [9.5825],
+
+    "os-nosdn-nofeature-noha:huawei-pod12:joid": [9.5875],
+
+    "os-nosdn-nofeature-ha:huawei-pod12:joid": [9.6345],
+
+    "os-odl-sfc-noha:huawei-virtual4:compass": [9.6535],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual2:fuel": [9.743],
+
+    "os-odl-sfc-noha:huawei-virtual3:compass": [9.82],
+
+    "os-odl-nofeature-noha:ericsson-virtual2:fuel": [9.8715],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual3:compass": [9.982],
+
+    "os-nosdn-bar-noha:huawei-virtual4:compass": [10.0195],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual4:compass": [10.1285],
+
+    "os-nosdn-nofeature-noha:huawei-virtual3:compass": [10.1335],
+
+    "os-nosdn-nofeature-noha:huawei-virtual2:compass": [10.22],
+
+    "os-nosdn-bar-noha:huawei-virtual3:compass": [10.2845],
+
+    "os-nosdn-ovs-noha:ericsson-virtual4:fuel": [10.4185],
+
+    "os-nosdn-ovs-noha:ericsson-virtual2:fuel": [10.4555],
+
+    "os-nosdn-kvm-noha:huawei-virtual3:compass": [10.5635],
+
+    "os-nosdn-kvm-noha:huawei-virtual4:compass": [10.6515],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual3:fuel": [10.9355],
+
+    "os-odl-nofeature-noha:ericsson-virtual4:fuel": [11.2015],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual3:compass": [12.984],
+
+    "os-nosdn-bar-ha:huawei-virtual3:compass": [13.306],
+
+    "os-nosdn-nofeature-ha:huawei-virtual3:compass": [13.721],
+
+    "os-nosdn-bar-ha:huawei-virtual4:compass": [14.133],
+
+    "os-nosdn-nofeature-ha:ericsson-pod1:fuel": [14.158],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual4:compass": [14.375],
+
+    "os-nosdn-nofeature-ha:huawei-virtual4:compass": [14.396],
+
+    "os-nosdn-kvm-ha:huawei-virtual4:compass": [14.9375],
+
+    "os-odl-sfc-ha:huawei-virtual3:compass": [14.957],
+
+    "os-nosdn-calipso-noha:lf-pod1:apex": [16.3445],
+
+    "os-nosdn-ovs-ha:lf-pod2:fuel": [16.478],
+
+    "os-nosdn-nofeature-ha:lf-pod2:fuel": [16.4895],
+
+    "os-odl-nofeature-noha:lf-pod1:apex": [16.55],
+
+    "os-nosdn-nofeature-noha:lf-pod1:apex": [16.5665],
+
+    "os-odl-sfc-noha:lf-pod1:apex": [16.598],
+
+    "os-ovn-nofeature-noha:lf-pod1:apex": [16.805],
+
+    "os-odl-nofeature-ha:lf-pod1:apex": [16.9095],
+
+    "os-nosdn-bar-ha:lf-pod1:apex": [17.494],
+
+    "os-nosdn-bar-noha:lf-pod1:apex": [17.4995],
+
+    "os-nosdn-nofeature-ha:lf-pod1:apex": [18.094],
+
+    "os-odl-nofeature-ha:arm-pod5:fuel": [18.744],
+
+    "os-nosdn-nofeature-ha:huawei-virtual1:compass": [19.8235],
+
+    "os-odl-nofeature-ha:lf-pod2:fuel": [20.758],
+
+    "os-nosdn-kvm-ha:huawei-virtual3:compass": [26.5245],
+
+    "os-nosdn-nofeature-ha:arm-pod6:fuel": [55.667],
+
+    "os-odl-nofeature-ha:arm-pod6:fuel": [56.175],
+
+    "os-nosdn-ovs-ha:arm-pod6:fuel": [57.86]
+
+}
+
+
+The influence of the scenario
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc010_scenario_fraser.png
+   :width: 800px
+   :alt: TC010 influence of scenario
+
+{
+
+    "os-nosdn-openbaton-ha": [7.5535],
+
+    "os-odl-nofeature-ha": [8.2535],
+
+    "os-odl-sfc-ha": [9.251],
+
+    "os-nosdn-nofeature-ha": [9.464],
+
+    "os-odl-sfc-noha": [9.8265],
+
+    "os-odl_l3-nofeature-ha": [9.836],
+
+    "os-odl_l3-nofeature-noha": [10.0565],
+
+    "os-nosdn-nofeature-noha": [10.079],
+
+    "os-nosdn-kvm-ha": [10.418],
+
+    "os-nosdn-ovs-noha": [10.43],
+
+    "os-nosdn-kvm-noha": [10.603],
+
+    "os-nosdn-bar-noha": [11.067],
+
+    "os-nosdn-bar-ha": [13.911],
+
+    "os-odl-nofeature-noha": [14.046],
+
+    "os-nosdn-calipso-noha": [16.3445],
+
+    "os-nosdn-ovs-ha": [16.478],
+
+    "os-ovn-nofeature-noha": [16.805]
+
+}
+
+
+The influence of the POD
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc010_pod_fraser.png
+   :width: 800px
+   :alt: TC010 influence of the POD
+
+{
+
+    "ericsson-pod1": [7.0645],
+
+    "intel-pod18": [7.4465],
+
+    "zte-pod2": [8.1865],
+
+    "huawei-pod2": [9.236],
+
+    "huawei-pod12": [9.615],
+
+    "ericsson-virtual2": [9.8925],
+
+    "huawei-virtual2": [10.22],
+
+    "ericsson-virtual4": [10.5465],
+
+    "ericsson-virtual3": [10.9355],
+
+    "huawei-virtual3": [10.95],
+
+    "huawei-virtual4": [11.557],
+
+    "lf-pod2": [16.5595],
+
+    "lf-pod1": [16.8395],
+
+    "arm-pod5": [18.744],
+
+    "huawei-virtual1": [19.8235],
+
+    "arm-pod6": [55.804]
+
+}
index b07ea89..f255b50 100644 (file)
@@ -260,3 +260,173 @@ The influence of the POD
 
 Fraser release
 --------------
+
+Test results per scenario and pod (lower is better):
+
+{
+
+    "os-nosdn-nofeature-ha:arm-pod6:fuel": [1],
+
+    "os-nosdn-nofeature-ha:ericsson-pod1:fuel": [1],
+
+    "os-nosdn-nofeature-ha:lf-pod2:fuel": [1],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual2:fuel": [1],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual3:fuel": [1],
+
+    "os-ovn-nofeature-noha:lf-pod1:apex": [1511.5],
+
+    "os-nosdn-kvm-noha:huawei-virtual3:compass": [2996],
+
+    "os-nosdn-bar-ha:huawei-virtual4:compass": [2997],
+
+    "os-nosdn-bar-noha:huawei-virtual4:compass": [2997],
+
+    "os-nosdn-kvm-ha:huawei-virtual4:compass": [2997],
+
+    "os-nosdn-nofeature-ha:huawei-virtual1:compass": [2997],
+
+    "os-nosdn-nofeature-ha:huawei-virtual3:compass": [2997],
+
+    "os-nosdn-nofeature-ha:huawei-virtual4:compass": [2997],
+
+    "os-odl-sfc-ha:huawei-virtual3:compass": [2997],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual3:compass": [2997],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual3:compass": [3000],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual4:compass": [3003],
+
+    "os-nosdn-bar-noha:huawei-virtual3:compass": [3011],
+
+    "os-nosdn-bar-ha:huawei-virtual3:compass": [3015.5],
+
+    "os-nosdn-kvm-noha:huawei-virtual4:compass": [3019],
+
+    "os-nosdn-nofeature-noha:huawei-virtual4:compass": [3021],
+
+    "os-odl-sfc-ha:huawei-virtual4:compass": [3021],
+
+    "os-nosdn-bar-ha:huawei-pod2:compass": [3022],
+
+    "os-nosdn-bar-ha:lf-pod1:apex": [3022],
+
+    "os-nosdn-bar-noha:lf-pod1:apex": [3022],
+
+    "os-nosdn-calipso-noha:lf-pod1:apex": [3022],
+
+    "os-nosdn-kvm-ha:huawei-pod2:compass": [3022],
+
+    "os-nosdn-nofeature-ha:huawei-pod12:joid": [3022],
+
+    "os-nosdn-nofeature-ha:huawei-pod2:compass": [3022],
+
+    "os-nosdn-nofeature-ha:intel-pod18:joid": [3022],
+
+    "os-nosdn-nofeature-ha:lf-pod1:apex": [3022],
+
+    "os-nosdn-nofeature-ha:zte-pod2:daisy": [3022],
+
+    "os-nosdn-nofeature-noha:huawei-pod12:joid": [3022],
+
+    "os-nosdn-nofeature-noha:intel-pod18:joid": [3022],
+
+    "os-nosdn-nofeature-noha:lf-pod1:apex": [3022],
+
+    "os-nosdn-openbaton-ha:intel-pod18:joid": [3022],
+
+    "os-odl-sfc-ha:huawei-pod2:compass": [3022],
+
+    "os-odl_l3-nofeature-ha:huawei-pod2:compass": [3022],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual4:compass": [3022],
+
+    "os-odl-sfc-noha:huawei-virtual4:compass": [3022.5],
+
+    "os-nosdn-nofeature-noha:huawei-virtual3:compass": [3023],
+
+    "os-odl-sfc-noha:huawei-virtual3:compass": [3023],
+
+    "os-nosdn-nofeature-noha:huawei-virtual2:compass": [3025]
+
+}
+
+
+The influence of the scenario
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc011_scenario_fraser.png
+   :width: 800px
+   :alt: TC011 influence of scenario
+
+{
+
+    "os-ovn-nofeature-noha": [1511.5],
+
+    "os-nosdn-kvm-noha": [2997],
+
+    "os-odl-sfc-ha": [3021],
+
+    "os-nosdn-bar-ha": [3022],
+
+    "os-nosdn-bar-noha": [3022],
+
+    "os-nosdn-calipso-noha": [3022],
+
+    "os-nosdn-kvm-ha": [3022],
+
+    "os-nosdn-nofeature-ha": [3022],
+
+    "os-nosdn-nofeature-noha": [3022],
+
+    "os-nosdn-openbaton-ha": [3022],
+
+    "os-odl_l3-nofeature-ha": [3022],
+
+    "os-odl_l3-nofeature-noha": [3022],
+
+    "os-odl-sfc-noha": [3023]
+
+}
+
+
+The influence of the POD
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc011_pod_fraser.png
+   :width: 800px
+   :alt: TC011 influence of the POD
+
+{
+
+    "arm-pod6": [1],
+
+    "ericsson-pod1": [1],
+
+    "ericsson-virtual2": [1],
+
+    "ericsson-virtual3": [1],
+
+    "lf-pod2": [1],
+
+    "huawei-virtual1": [2997],
+
+    "huawei-virtual3": [2999],
+
+    "huawei-virtual4": [3002],
+
+    "huawei-pod12": [3022],
+
+    "huawei-pod2": [3022],
+
+    "intel-pod18": [3022],
+
+    "lf-pod1": [3022],
+
+    "zte-pod2": [3022],
+
+    "huawei-virtual2": [3025]
+
+}
index c28eb1f..71d69cd 100644 (file)
@@ -297,3 +297,217 @@ The influence of the POD
 
 Fraser release
 --------------
+
+Test results per scenario and pod (higher is better):
+
+{
+
+    "os-nosdn-nofeature-ha:lf-pod2:fuel": [21421.795],
+
+    "os-odl-sfc-noha:lf-pod1:apex": [21075],
+
+    "os-odl-sfc-ha:lf-pod1:apex": [21017.44],
+
+    "os-nosdn-bar-noha:lf-pod1:apex": [20991.46],
+
+    "os-nosdn-bar-ha:lf-pod1:apex": [20812.405],
+
+    "os-ovn-nofeature-noha:lf-pod1:apex": [20694.035],
+
+    "os-nosdn-nofeature-noha:lf-pod1:apex": [20672.765],
+
+    "os-odl-nofeature-ha:lf-pod2:fuel": [20269.65],
+
+    "os-nosdn-calipso-noha:lf-pod1:apex": [20186.32],
+
+    "os-odl-nofeature-noha:lf-pod1:apex": [19959.915],
+
+    "os-nosdn-ovs-ha:lf-pod2:fuel": [19719.38],
+
+    "os-odl-nofeature-ha:lf-pod1:apex": [19654.505],
+
+    "os-nosdn-nofeature-ha:lf-pod1:apex": [19391.145],
+
+    "os-nosdn-nofeature-noha:intel-pod18:joid": [19378.64],
+
+    "os-odl-nofeature-ha:ericsson-pod1:fuel": [19103.43],
+
+    "os-nosdn-nofeature-ha:intel-pod18:joid": [18688.695],
+
+    "os-nosdn-openbaton-ha:intel-pod18:joid": [18557.95],
+
+    "os-nosdn-nofeature-ha:ericsson-pod1:fuel": [17088.61],
+
+    "os-nosdn-ovs-ha:ericsson-pod1:fuel": [17040.78],
+
+    "os-nosdn-ovs-noha:ericsson-virtual2:fuel": [16057.235],
+
+    "os-odl-nofeature-noha:ericsson-virtual4:fuel": [15622.355],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual2:fuel": [15422.235],
+
+    "os-odl-sfc-ha:huawei-pod2:compass": [15403.09],
+
+    "os-odl-nofeature-noha:ericsson-virtual2:fuel": [15141.58],
+
+    "os-nosdn-bar-ha:huawei-pod2:compass": [14922.37],
+
+    "os-odl_l3-nofeature-ha:huawei-pod2:compass": [14864.195],
+
+    "os-nosdn-nofeature-ha:huawei-pod2:compass": [14856.295],
+
+    "os-nosdn-kvm-ha:huawei-pod2:compass": [14796.035],
+
+    "os-odl-sfc-noha:huawei-virtual4:compass": [14484.375],
+
+    "os-nosdn-nofeature-ha:huawei-pod12:joid": [14441.955],
+
+    "os-odl-sfc-noha:huawei-virtual3:compass": [14373],
+
+    "os-nosdn-nofeature-noha:huawei-virtual4:compass": [14330.44],
+
+    "os-nosdn-ovs-noha:ericsson-virtual4:fuel": [14320.305],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual3:compass": [14253.715],
+
+    "os-nosdn-nofeature-ha:huawei-virtual4:compass": [14203.655],
+
+    "os-nosdn-nofeature-noha:huawei-virtual3:compass": [14179.93],
+
+    "os-odl-nofeature-ha:zte-pod2:daisy": [14177.135],
+
+    "os-nosdn-nofeature-ha:zte-pod2:daisy": [14150.825],
+
+    "os-nosdn-nofeature-noha:huawei-pod12:joid": [14100.87],
+
+    "os-nosdn-bar-noha:huawei-virtual4:compass": [14033.36],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual4:compass": [13963.73],
+
+    "os-nosdn-kvm-noha:huawei-virtual3:compass": [13874.775],
+
+    "os-nosdn-kvm-noha:huawei-virtual4:compass": [13805.65],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual3:compass": [13754.63],
+
+    "os-nosdn-nofeature-noha:huawei-virtual2:compass": [13702.92],
+
+    "os-nosdn-bar-ha:huawei-virtual3:compass": [13638.115],
+
+    "os-odl-sfc-ha:huawei-virtual3:compass": [13637.83],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual4:compass": [13635.66],
+
+    "os-nosdn-bar-noha:huawei-virtual3:compass": [13635.58],
+
+    "os-nosdn-bar-ha:huawei-virtual4:compass": [13544.95],
+
+    "os-nosdn-nofeature-ha:huawei-virtual3:compass": [13514.27],
+
+    "os-nosdn-nofeature-ha:huawei-virtual1:compass": [13496.45],
+
+    "os-odl-sfc-ha:huawei-virtual4:compass": [13475.38],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual3:fuel": [12733.19],
+
+    "os-nosdn-kvm-ha:huawei-virtual4:compass": [12682.805],
+
+    "os-odl-nofeature-ha:arm-pod5:fuel": [4326.11],
+
+    "os-nosdn-nofeature-ha:arm-pod6:fuel": [3824.13],
+
+    "os-odl-nofeature-ha:arm-pod6:fuel": [3797.795],
+
+    "os-nosdn-ovs-ha:arm-pod6:fuel": [3749.91]
+
+}
+
+
+The influence of the scenario
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc012_scenario_fraser.png
+   :width: 800px
+   :alt: TC012 influence of scenario
+
+{
+
+    "os-ovn-nofeature-noha": [20694.035],
+
+    "os-nosdn-calipso-noha": [20186.32],
+
+    "os-nosdn-openbaton-ha": [18557.95],
+
+    "os-nosdn-ovs-ha": [17048.17],
+
+    "os-odl-nofeature-noha": [16191.125],
+
+    "os-nosdn-ovs-noha": [15790.32],
+
+    "os-nosdn-bar-ha": [14833.97],
+
+    "os-odl-sfc-ha": [14828.72],
+
+    "os-odl_l3-nofeature-ha": [14801.25],
+
+    "os-nosdn-kvm-ha": [14700.1],
+
+    "os-nosdn-nofeature-ha": [14610.48],
+
+    "os-nosdn-nofeature-noha": [14555.975],
+
+    "os-odl-sfc-noha": [14508.14],
+
+    "os-nosdn-bar-noha": [14395.22],
+
+    "os-odl-nofeature-ha": [14231.245],
+
+    "os-odl_l3-nofeature-noha": [14161.58],
+
+    "os-nosdn-kvm-noha": [13845.685]
+
+}
+
+
+The influence of the POD
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc012_pod_fraser.png
+   :width: 800px
+   :alt: TC012 influence of the POD
+
+{
+
+    "lf-pod1": [20552.9],
+
+    "lf-pod2": [20058.925],
+
+    "ericsson-pod1": [18930.78],
+
+    "intel-pod18": [18757.545],
+
+    "ericsson-virtual4": [15389.465],
+
+    "ericsson-virtual2": [15343.79],
+
+    "huawei-pod2": [14870.78],
+
+    "zte-pod2": [14157.99],
+
+    "huawei-pod12": [14126.99],
+
+    "huawei-virtual3": [13929.67],
+
+    "huawei-virtual4": [13847.155],
+
+    "huawei-virtual2": [13702.92],
+
+    "huawei-virtual1": [13496.45],
+
+    "ericsson-virtual3": [12733.19],
+
+    "arm-pod5": [4326.11],
+
+    "arm-pod6": [3809.885]
+
+}
index 34d4ad0..a2eeb63 100644 (file)
@@ -296,3 +296,217 @@ The influence of the POD
 
 Fraser release
 --------------
+
+Test results per scenario and pod (higher is better):
+
+{
+
+    "os-nosdn-nofeature-ha:lf-pod2:fuel": [3747.3],
+
+    "os-nosdn-calipso-noha:lf-pod1:apex": [3727.2],
+
+    "os-odl-nofeature-ha:lf-pod1:apex": [3726.5],
+
+    "os-ovn-nofeature-noha:lf-pod1:apex": [3723.8],
+
+    "os-odl-nofeature-noha:lf-pod1:apex": [3718.9],
+
+    "os-nosdn-nofeature-noha:lf-pod1:apex": [3717.75],
+
+    "os-nosdn-nofeature-ha:lf-pod1:apex": [3706.5],
+
+    "os-odl-nofeature-ha:lf-pod2:fuel": [3704.9],
+
+    "os-nosdn-ovs-ha:lf-pod2:fuel": [3687.7],
+
+    "os-nosdn-bar-noha:lf-pod1:apex": [3635.4],
+
+    "os-nosdn-bar-ha:lf-pod1:apex": [3632.55],
+
+    "os-odl-sfc-noha:lf-pod1:apex": [3569],
+
+    "os-nosdn-nofeature-noha:intel-pod18:joid": [3432.1],
+
+    "os-odl-nofeature-ha:ericsson-pod1:fuel": [3133.85],
+
+    "os-nosdn-ovs-ha:ericsson-pod1:fuel": [3079.8],
+
+    "os-nosdn-nofeature-ha:intel-pod18:joid": [3074.75],
+
+    "os-nosdn-openbaton-ha:intel-pod18:joid": [2976.2],
+
+    "os-nosdn-nofeature-ha:zte-pod2:daisy": [2910.95],
+
+    "os-odl-nofeature-ha:zte-pod2:daisy": [2801.1],
+
+    "os-nosdn-ovs-noha:ericsson-virtual2:fuel": [2603],
+
+    "os-odl-nofeature-noha:ericsson-virtual2:fuel": [2559.7],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual2:fuel": [2539.1],
+
+    "os-odl_l3-nofeature-ha:huawei-pod2:compass": [2530.5],
+
+    "os-nosdn-nofeature-ha:huawei-pod2:compass": [2529.4],
+
+    "os-odl-sfc-ha:huawei-pod2:compass": [2528.9],
+
+    "os-odl-nofeature-noha:ericsson-virtual4:fuel": [2527.8],
+
+    "os-nosdn-bar-ha:huawei-pod2:compass": [2527.4],
+
+    "os-nosdn-kvm-ha:huawei-pod2:compass": [2517.8],
+
+    "os-nosdn-nofeature-noha:huawei-virtual4:compass": [2472.4],
+
+    "os-nosdn-nofeature-ha:huawei-virtual4:compass": [2469.1],
+
+    "os-odl-sfc-noha:huawei-virtual3:compass": [2452.05],
+
+    "os-odl-sfc-noha:huawei-virtual4:compass": [2438.7],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual3:compass": [2418.4],
+
+    "os-nosdn-ovs-noha:ericsson-virtual4:fuel": [2404.35],
+
+    "os-nosdn-kvm-noha:huawei-virtual3:compass": [2391],
+
+    "os-nosdn-kvm-noha:huawei-virtual4:compass": [2376.75],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual4:compass": [2376.2],
+
+    "os-nosdn-nofeature-noha:huawei-virtual3:compass": [2359.45],
+
+    "os-nosdn-bar-noha:huawei-virtual4:compass": [2353.3],
+
+    "os-odl-sfc-ha:huawei-virtual3:compass": [2351.9],
+
+    "os-nosdn-bar-ha:huawei-virtual3:compass": [2339.4],
+
+    "os-odl-sfc-ha:huawei-virtual4:compass": [2335.6],
+
+    "os-nosdn-bar-ha:huawei-virtual4:compass": [2328],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual3:compass": [2324.5],
+
+    "os-nosdn-bar-noha:huawei-virtual3:compass": [2317.3],
+
+    "os-nosdn-nofeature-ha:huawei-virtual3:compass": [2313.95],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual4:compass": [2308.1],
+
+    "os-nosdn-nofeature-noha:huawei-virtual2:compass": [2299.3],
+
+    "os-nosdn-kvm-ha:huawei-virtual4:compass": [2250.4],
+
+    "os-nosdn-nofeature-noha:huawei-pod12:joid": [2229.7],
+
+    "os-nosdn-nofeature-ha:huawei-pod12:joid": [2228.8],
+
+    "os-nosdn-nofeature-ha:huawei-virtual1:compass": [2171.3],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual3:fuel": [2104.8],
+
+    "os-nosdn-nofeature-ha:ericsson-pod1:fuel": [1961.35],
+
+    "os-nosdn-ovs-ha:arm-pod5:fuel": [1764.2],
+
+    "os-odl-nofeature-ha:arm-pod5:fuel": [1730.95],
+
+    "os-nosdn-ovs-ha:arm-pod6:fuel": [715.55],
+
+    "os-odl-nofeature-ha:arm-pod6:fuel": [715.4],
+
+    "os-nosdn-nofeature-ha:arm-pod6:fuel": [715.25]
+
+}
+
+
+The influence of the scenario
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc014_scenario_fraser.png
+   :width: 800px
+   :alt: TC014 influence of scenario
+
+{
+
+    "os-nosdn-calipso-noha": [3727.2],
+
+    "os-ovn-nofeature-noha": [3723.8],
+
+    "os-odl-nofeature-noha": [3128.05],
+
+    "os-nosdn-openbaton-ha": [2976.2],
+
+    "os-nosdn-ovs-ha": [2814.5],
+
+    "os-odl-nofeature-ha": [2801.4],
+
+    "os-nosdn-nofeature-ha": [2649.7],
+
+    "os-nosdn-ovs-noha": [2587.3],
+
+    "os-odl_l3-nofeature-ha": [2528.45],
+
+    "os-odl-sfc-ha": [2527.6],
+
+    "os-nosdn-bar-ha": [2526.55],
+
+    "os-nosdn-kvm-ha": [2516.95],
+
+    "os-odl-sfc-noha": [2453.65],
+
+    "os-nosdn-bar-noha": [2447.7],
+
+    "os-nosdn-nofeature-noha": [2443.85],
+
+    "os-odl_l3-nofeature-noha": [2394.3],
+
+    "os-nosdn-kvm-noha": [2379.7]
+
+}
+
+
+The influence of the POD
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc014_pod_fraser.png
+   :width: 800px
+   :alt: TC014 influence of the POD
+
+{
+
+    "lf-pod2": [3737.6],
+
+    "lf-pod1": [3702.7],
+
+    "ericsson-pod1": [3131.6],
+
+    "intel-pod18": [3098.1],
+
+    "zte-pod2": [2831.4],
+
+    "ericsson-virtual2": [2559.7],
+
+    "huawei-pod2": [2528.9],
+
+    "ericsson-virtual4": [2527.8],
+
+    "huawei-virtual3": [2379.1],
+
+    "huawei-virtual4": [2362.1],
+
+    "huawei-virtual2": [2299.3],
+
+    "huawei-pod12": [2229],
+
+    "huawei-virtual1": [2171.3],
+
+    "ericsson-virtual3": [2104.8],
+
+    "arm-pod5": [1764.2],
+
+    "arm-pod6": [715.4]
+
+}
index 06e2ec9..4cd3be3 100644 (file)
@@ -298,3 +298,219 @@ The influence of the POD
 
 Fraser release
 --------------
+
+Test results per scenario and pod (higher is better):
+
+{
+
+    "os-nosdn-nofeature-noha:intel-pod18:joid": [18382.49],
+
+    "os-nosdn-openbaton-ha:intel-pod18:joid": [16774.52],
+
+    "os-nosdn-nofeature-ha:intel-pod18:joid": [16680.305],
+
+    "os-nosdn-ovs-ha:arm-pod6:fuel": [11925.22],
+
+    "os-nosdn-nofeature-ha:arm-pod6:fuel": [11895.71],
+
+    "os-odl-nofeature-ha:arm-pod6:fuel": [11880.7],
+
+    "os-nosdn-nofeature-ha:ericsson-pod1:fuel": [9471.095],
+
+    "os-odl-nofeature-ha:zte-pod2:daisy": [9375.33],
+
+    "os-nosdn-nofeature-ha:zte-pod2:daisy": [9372.95],
+
+    "os-odl-nofeature-ha:ericsson-pod1:fuel": [9174.36],
+
+    "os-nosdn-nofeature-noha:huawei-pod12:joid": [9051.57],
+
+    "os-nosdn-nofeature-ha:huawei-pod12:joid": [8894.74],
+
+    "os-odl_l3-nofeature-ha:huawei-pod2:compass": [8857.23],
+
+    "os-nosdn-nofeature-ha:huawei-pod2:compass": [8855.8],
+
+    "os-nosdn-bar-ha:huawei-pod2:compass": [8840.94],
+
+    "os-odl-sfc-ha:huawei-pod2:compass": [8826.23],
+
+    "os-nosdn-nofeature-noha:huawei-virtual4:compass": [8039.48],
+
+    "os-nosdn-nofeature-noha:huawei-virtual2:compass": [7670.21],
+
+    "os-nosdn-ovs-ha:arm-pod5:fuel": [7590.9],
+
+    "os-odl-sfc-noha:huawei-virtual4:compass": [7579.625],
+
+    "os-nosdn-bar-noha:huawei-virtual3:compass": [7511.775],
+
+    "os-odl-nofeature-ha:arm-pod5:fuel": [7475.16],
+
+    "os-nosdn-bar-noha:huawei-virtual4:compass": [7435.08],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual2:fuel": [7426.79],
+
+    "os-nosdn-nofeature-ha:huawei-virtual4:compass": [7362.8],
+
+    "os-nosdn-kvm-noha:huawei-virtual4:compass": [7263.45],
+
+    "os-nosdn-nofeature-noha:huawei-virtual3:compass": [7262.72],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual3:compass": [7241.07],
+
+    "os-odl-nofeature-noha:ericsson-virtual2:fuel": [7219.21],
+
+    "os-nosdn-kvm-noha:huawei-virtual3:compass": [7174.33],
+
+    "os-odl-sfc-noha:huawei-virtual3:compass": [7170.795],
+
+    "os-odl-nofeature-noha:lf-pod1:apex": [7158.335],
+
+    "os-nosdn-kvm-ha:huawei-pod2:compass": [7122.45],
+
+    "os-odl-sfc-ha:huawei-virtual4:compass": [7104.9],
+
+    "os-nosdn-ovs-noha:ericsson-virtual2:fuel": [7044.37],
+
+    "os-nosdn-bar-ha:huawei-virtual3:compass": [7011.075],
+
+    "os-nosdn-ovs-ha:ericsson-pod1:fuel": [6950.28],
+
+    "os-nosdn-ovs-noha:ericsson-virtual4:fuel": [6918.31],
+
+    "os-nosdn-bar-ha:huawei-virtual4:compass": [6903.11],
+
+    "os-nosdn-nofeature-ha:lf-pod2:fuel": [6880.98],
+
+    "os-odl-sfc-ha:lf-pod1:apex": [6863.39],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual3:compass": [6851.54],
+
+    "os-nosdn-nofeature-noha:lf-pod1:apex": [6834.75],
+
+    "os-nosdn-calipso-noha:lf-pod1:apex": [6833.92],
+
+    "os-nosdn-ovs-ha:lf-pod2:fuel": [6814.68],
+
+    "os-ovn-nofeature-noha:lf-pod1:apex": [6809.44],
+
+    "os-odl_l3-nofeature-ha:huawei-virtual4:compass": [6784.48],
+
+    "os-nosdn-nofeature-ha:lf-pod1:apex": [6737.64],
+
+    "os-nosdn-bar-noha:lf-pod1:apex": [6708.61],
+
+    "os-nosdn-bar-ha:lf-pod1:apex": [6697.2],
+
+    "os-odl-nofeature-ha:lf-pod1:apex": [6626.51],
+
+    "os-odl-sfc-noha:lf-pod1:apex": [6609.57],
+
+    "os-odl-sfc-ha:huawei-virtual3:compass": [6606.87],
+
+    "os-odl_l3-nofeature-noha:huawei-virtual4:compass": [6547.39],
+
+    "os-odl-nofeature-ha:lf-pod2:fuel": [6465.48],
+
+    "os-odl-nofeature-noha:ericsson-virtual4:fuel": [6413],
+
+    "os-nosdn-kvm-ha:huawei-virtual4:compass": [6409.075],
+
+    "os-nosdn-nofeature-ha:huawei-virtual3:compass": [6128.79],
+
+    "os-nosdn-nofeature-noha:ericsson-virtual3:fuel": [5835.59],
+
+    "os-nosdn-nofeature-ha:huawei-virtual1:compass": [5617.12]
+
+}
+
+
+The influence of the scenario
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc069_scenario_fraser.png
+   :width: 800px
+   :alt: TC069 influence of scenario
+
+{
+
+    "os-nosdn-openbaton-ha": [16774.52],
+
+    "os-odl-nofeature-ha": [9363.69],
+
+    "os-nosdn-nofeature-ha": [8878.01],
+
+    "os-odl_l3-nofeature-ha": [8748.4],
+
+    "os-odl-sfc-ha": [8708.045],
+
+    "os-nosdn-nofeature-noha": [7426.79],
+
+    "os-nosdn-kvm-noha": [7230.79],
+
+    "os-odl-sfc-noha": [7224.11],
+
+    "os-odl-nofeature-noha": [7187.84],
+
+    "os-nosdn-ovs-noha": [7044.37],
+
+    "os-nosdn-bar-ha": [6947.87],
+
+    "os-odl_l3-nofeature-noha": [6895.96],
+
+    "os-nosdn-kvm-ha": [6890.92],
+
+    "os-nosdn-calipso-noha": [6833.92],
+
+    "os-nosdn-ovs-ha": [6833.495],
+
+    "os-nosdn-bar-noha": [6811.66],
+
+    "os-ovn-nofeature-noha": [6809.44]
+
+}
+
+
+The influence of the POD
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc069_pod_fraser.png
+   :width: 800px
+   :alt: TC069 influence of the POD
+
+{
+
+    "intel-pod18": [16939.24],
+
+    "arm-pod6": [11895.71],
+
+    "zte-pod2": [9375.33],
+
+    "ericsson-pod1": [9140.42],
+
+    "huawei-pod12": [8993.37],
+
+    "huawei-pod2": [8794.01],
+
+    "huawei-virtual2": [7670.21],
+
+    "arm-pod5": [7479.32],
+
+    "ericsson-virtual2": [7219.21],
+
+    "huawei-virtual4": [7059.045],
+
+    "huawei-virtual3": [7023.57],
+
+    "lf-pod2": [6834.7],
+
+    "lf-pod1": [6775.27],
+
+    "ericsson-virtual4": [6522.86],
+
+    "ericsson-virtual3": [5835.59],
+
+    "huawei-virtual1": [5617.12]
+
+}
index d8a9f54..92bc699 100644 (file)
@@ -70,8 +70,6 @@ The influence of the scenario
    :width: 800px
    :alt: TC082 influence of scenario
 
-the influence of the scenario
-
 {
 
     "os-nosdn-nofeature-ha": [505],
@@ -88,8 +86,6 @@ The influence of the POD
    :width: 800px
    :alt: TC082 influence of the POD
 
-the influence of the POD
-
 {
 
     "huawei-pod12": [316],
@@ -127,3 +123,65 @@ the influence of the POD
 
 Fraser release
 --------------
+
+Test results per scenario and pod (lower is better):
+
+{
+
+    "os-nosdn-nofeature-ha:zte-pod2:daisy": [306.5],
+
+    "os-nosdn-nofeature-ha:lf-pod2:fuel": [337.5],
+
+    "os-nosdn-nofeature-ha:intel-pod18:joid": [343.5],
+
+    "os-nosdn-nofeature-ha:huawei-pod12:joid": [399],
+
+    "os-nosdn-nofeature-ha:lf-pod1:apex": [454],
+
+    "os-nosdn-nofeature-ha:huawei-pod2:compass": [544.5],
+
+    "os-nosdn-nofeature-ha:huawei-virtual4:compass": [1138],
+
+    "os-nosdn-nofeature-ha:ericsson-pod1:fuel": [1305],
+
+    "os-nosdn-nofeature-ha:huawei-virtual3:compass": [1433],
+
+    "os-nosdn-nofeature-ha:huawei-virtual1:compass": [1470],
+
+    "os-nosdn-nofeature-ha:arm-pod6:fuel": [1738.5]
+
+}
+
+
+The influence of the POD
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc082_pod_fraser.png
+   :width: 800px
+   :alt: TC082 influence of the POD
+
+{
+
+    "zte-pod2": [306.5],
+
+    "lf-pod2": [337.5],
+
+    "intel-pod18": [343.5],
+
+    "huawei-pod12": [399],
+
+    "lf-pod1": [454],
+
+    "huawei-pod2": [544.5],
+
+    "huawei-virtual4": [1138],
+
+    "ericsson-pod1": [1305],
+
+    "huawei-virtual3": [1433],
+
+    "huawei-virtual1": [1470],
+
+    "arm-pod6": [1738.5]
+
+}
index f846571..0389eaa 100644 (file)
@@ -70,8 +70,6 @@ The influence of the scenario
    :width: 800px
    :alt: TC083 influence of scenario
 
-the influence of the scenario
-
 {
 
     "os-nosdn-nofeature-ha": [1109.12],
@@ -88,8 +86,6 @@ The influence of the POD
    :width: 800px
    :alt: TC083 influence of the POD
 
-the influence of the POD
-
 {
 
     "lf-pod1": [2204.42],
@@ -127,3 +123,65 @@ the influence of the POD
 
 Fraser release
 --------------
+
+Test results per scenario and pod (higher is better):
+
+{
+
+    "os-nosdn-nofeature-ha:lf-pod2:fuel": [1893.39],
+
+    "os-nosdn-nofeature-ha:zte-pod2:daisy": [1543.995],
+
+    "os-nosdn-nofeature-ha:lf-pod1:apex": [1480.86],
+
+    "os-nosdn-nofeature-ha:intel-pod18:joid": [1417.015],
+
+    "os-nosdn-nofeature-ha:huawei-pod12:joid": [1028.55],
+
+    "os-nosdn-nofeature-ha:huawei-pod2:compass": [1007.65],
+
+    "os-nosdn-nofeature-ha:ericsson-pod1:fuel": [811.795],
+
+    "os-nosdn-nofeature-ha:huawei-virtual4:compass": [552.95],
+
+    "os-nosdn-nofeature-ha:arm-pod6:fuel": [227.655],
+
+    "os-nosdn-nofeature-ha:huawei-virtual1:compass": [216.63],
+
+    "os-nosdn-nofeature-ha:huawei-virtual3:compass": [59.255]
+
+}
+
+
+The influence of the POD
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. image:: images/tc083_pod_fraser.png
+   :width: 800px
+   :alt: TC083 influence of the POD
+
+{
+
+    "lf-pod2": [1893.39],
+
+    "zte-pod2": [1543.995],
+
+    "lf-pod1": [1480.86],
+
+    "intel-pod18": [1417.015],
+
+    "huawei-pod12": [1028.55],
+
+    "huawei-pod2": [1007.65],
+
+    "ericsson-pod1": [811.795],
+
+    "huawei-virtual4": [552.95],
+
+    "arm-pod6": [227.655],
+
+    "huawei-virtual1": [216.63],
+
+    "huawei-virtual3": [59.255]
+
+}
index 04d5350..dbe92b8 100755 (executable)
@@ -1,16 +1,42 @@
+..
+      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.
+
+      Convention for heading levels in Yardstick documentation:
+
+      =======  Heading 0 (reserved for the title in a document)
+      -------  Heading 1
+      ~~~~~~~  Heading 2
+      +++++++  Heading 3
+      '''''''  Heading 4
+
+      Avoid deeper levels because they do not render well.
+
 Introduction
-=============
+------------
 
-Yardstick is a project dealing with performance testing. Yardstick produces its own test cases but can also be considered as a framework to support feature project testing.
+Yardstick is a project dealing with performance testing. Yardstick produces
+its own test cases but can also be considered as a framework to support feature
+project testing.
 
-Yardstick developed a test API that can be used by any OPNFV project. Therefore there are many ways to contribute to Yardstick.
+Yardstick developed a test API that can be used by any OPNFV project. Therefore
+there are many ways to contribute to Yardstick.
 
 You can:
 
 * Develop new test cases
 * Review codes
 * Develop Yardstick API / framework
-* Develop Yardstick grafana dashboards and  Yardstick reporting page
+* Develop Yardstick grafana dashboards and Yardstick reporting page
 * Write Yardstick documentation
 
 This developer guide describes how to interact with the Yardstick project.
@@ -19,28 +45,30 @@ part is a list of “How to” to help you to join the Yardstick family whatever
 your field of interest is.
 
 Where can I find some help to start?
---------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 .. _`user guide`: http://artifacts.opnfv.org/yardstick/danube/1.0/docs/stesting_user_userguide/index.html
 .. _`wiki page`: https://wiki.opnfv.org/display/yardstick/
 
 This guide is made for you. You can have a look at the `user guide`_.
 There are also references on documentation, video tutorials, tips in the
-project `wiki page`_. You can also directly contact us by mail with [Yardstick] prefix in the title at opnfv-tech-discuss@lists.opnfv.org or on the IRC chan #opnfv-yardstick.
+project `wiki page`_. You can also directly contact us by mail with [Yardstick]
+prefix in the subject at opnfv-tech-discuss@lists.opnfv.org or on the IRC chan
+#opnfv-yardstick.
 
 
 Yardstick developer areas
-==========================
+-------------------------
 
 Yardstick framework
---------------------
+~~~~~~~~~~~~~~~~~~~
 
-Yardstick can be considered as a framework. Yardstick is release as a docker
+Yardstick can be considered as a framework. Yardstick is released as a docker
 file, including tools, scripts and a CLI to prepare the environement and run
-tests. It simplifies the integration of external test suites in CI pipeline
-and provide commodity tools to collect and display results.
+tests. It simplifies the integration of external test suites in CI pipelines
+and provides commodity tools to collect and display results.
 
-Since Danube, test categories also known as tiers have been created to group
+Since Danube, test categories (also known as tiers) have been created to group
 similar tests, provide consistant sub-lists and at the end optimize test
 duration for CI (see How To section).
 
@@ -56,44 +84,54 @@ The tiers are:
 
 
 How Todos?
-===========
+----------
 
 How Yardstick works?
----------------------
+~~~~~~~~~~~~~~~~~~~~
 
 The installation and configuration of the Yardstick is described in the `user guide`_.
 
 How to work with test cases?
-----------------------------
-
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-**Sample Test cases**
+Sample Test cases
++++++++++++++++++
 
-Yardstick provides many sample test cases which are located at "samples" directory of repo.
+Yardstick provides many sample test cases which are located at ``samples`` directory of repo.
 
-Sample test cases are designed as following goals:
+Sample test cases are designed with the following goals:
 
-1. Helping user better understand yardstick features(including new feature and new test capacity).
+1. Helping user better understand Yardstick features (including new feature and
+   new test capacity).
 
-2. Helping developer to debug his new feature and test case before it is offical released.
+2. Helping developer to debug a new feature and test case before it is
+   offically released.
 
-3. Helping other developers understand and verify the new patch before the patch merged.
+3. Helping other developers understand and verify the new patch before the
+   patch is merged.
 
-So developers should upload your sample test case as well when they are trying to upload a new patch which is about the yardstick new test case or new feature.
+Developers should upload their sample test cases as well when they are
+uploading a new patch which is about the Yardstick new test case or new feature.
 
 
-**OPNFV Release Test cases**
+OPNFV Release Test cases
+++++++++++++++++++++++++
 
-OPNFV Release test cases which are located at "tests/opnfv/test_cases" of repo.
-those test cases are runing by OPNFV CI jobs, It means those test cases should be more mature than sample test cases.
-OPNFV scenario owners can select related test cases and add them into the test suites which is represent the scenario.
+OPNFV Release test cases are located at ``yardstick/tests/opnfv/test_cases``.
+These test cases are run by OPNFV CI jobs, which means these test cases should
+be more mature than sample test cases.
+OPNFV scenario owners can select related test cases and add them into the test
+suites which represent their scenario.
 
 
-**Test case Description File**
+Test case Description File
+++++++++++++++++++++++++++
 
 This section will introduce the meaning of the Test case description file.
-we will use ping.yaml as a example to show you how to understand the test case description file.
-In this Yaml file, you can easily find it consists of two sections. One is “Scenarios”,  the other is “Context”.::
+we will use ping.yaml as a example to show you how to understand the test case
+description file.
+This ``yaml`` file consists of two sections. One is ``scenarios``,  the other
+is ``context``.::
 
   ---
     # Sample benchmark task config file
@@ -150,18 +188,32 @@ In this Yaml file, you can easily find it consists of two sections. One is “Sc
          {% endif %}
 
 
-"Contexts" section is the description of pre-condition of testing. As ping.yaml shown, you can configure the image, flavor , name ,affinity and network of Test VM(servers),  with this section, you will get a pre-condition env for Testing.
-Yardstick will automatic setup the stack which are described in this section.
-In fact, yardstick use convert this section to heat template and setup the VMs by heat-client (Meanwhile, yardstick can support to convert this section to Kubernetes template to setup containers).
-
-Two Test VMs(athena and ares) are configured by keyword "servers".
-"flavor" will determine how many vCPU, how much memory for test VMs.
-As "yardstick-flavor" is a basic flavor which will be automatically created when you run command "yardstick env prepare". "yardstick-flavor" is "1 vCPU 1G RAM,3G Disk".
-"image" is the image name of test VMs. if you use cirros.3.5.0, you need fill the username of this image into "user". the "policy" of placement of Test VMs have two values (affinity and availability).
-"availability" means anti-affinity. In "network" section, you can configure which provide network and physical_network you want Test VMs use.
-you may need to configure segmentation_id when your network is vlan.
-
-Moreover, you can configure your specific flavor as below, yardstick will setup the stack for you. ::
+The ``contexts`` section is the description of pre-condition of testing. As
+``ping.yaml`` shows, you can configure the image, flavor, name, affinity and
+network of Test VM (servers),  with this section, you will get a pre-condition
+env for Testing.
+Yardstick will automatically setup the stack which are described in this
+section.
+Yardstick converts this section to heat template and sets up the VMs with
+heat-client (Yardstick can also support to convert this section to Kubernetes
+template to setup containers).
+
+In the examples above, two Test VMs (athena and ares) are configured by
+keyword ``servers``.
+``flavor`` will determine how many vCPU, how much memory for test VMs.
+As ``yardstick-flavor`` is a basic flavor which will be automatically created
+when you run command ``yardstick env prepare``. ``yardstick-flavor`` is
+``1 vCPU 1G RAM,3G Disk``.
+``image`` is the image name of test VMs. If you use ``cirros.3.5.0``, you need
+fill the username of this image into ``user``.
+The ``policy`` of placement of Test VMs have two values (``affinity`` and
+``availability``). ``availability`` means anti-affinity.
+In the ``network`` section, you can configure which ``provider`` network and
+``physical_network`` you want Test VMs to use.
+You may need to configure ``segmentation_id`` when your network is vlan.
+
+Moreover, you can configure your specific flavor as below, Yardstick will setup
+the stack for you. ::
 
   flavor:
     name: yardstick-new-flavor
@@ -170,7 +222,8 @@ Moreover, you can configure your specific flavor as below, yardstick will setup
     disk: 2
 
 
-Besides default heat stack, yardstick also allow you to setup other two types stack. they are "Node" and "Kubernetes". ::
+Besides default ``Heat`` context, Yardstick also allows you to setup two other
+types of context. They are ``Node`` and ``Kubernetes``. ::
 
   context:
     type: Kubernetes
@@ -183,48 +236,64 @@ and ::
     name: LF
 
 
+The ``scenarios`` section is the description of testing steps, you can
+orchestrate the complex testing step through scenarios.
 
-"Scenarios" section is the description of testing step, you can orchestrate the complex testing step through orchestrate scenarios.
+Each scenario will do one testing step.
+In one scenario, you can configure the type of scenario (operation), ``runner``
+type and ``sla`` of the scenario.
 
-Each scenario will do one testing step, In one scenario, you can configure the type of scenario(operation), runner type and SLA of the scenario.
+For TC002, We only have one step, which is Ping from host VM to target VM. In
+this step, we also have some detailed operations implemented (such as ssh to
+VM, ping from VM1 to VM2. Get the latency, verify the SLA, report the result).
 
-For TC002, We only have one step , that is Ping from host VM to target VM. In this step, we also have some detail operation implement ( such as ssh to VM, ping from VM1 to VM2. Get the latency, verify the SLA, report the result).
+If you want to get this implementation details implement, you can check with
+the scenario.py file. For Ping scenario, you can find it in Yardstick repo
+(``yardstick/yardstick/benchmark/scenarios/networking/ping.py``).
 
-If you want to get this detail implement , you can check with the scenario.py file. For Ping scenario, you can find it in yardstick repo ( yardstick / yardstick / benchmark / scenarios / networking / ping.py)
+After you select the type of scenario (such as Ping), you will select one type
+of ``runner``, there are 4 types of runner. ``Iteration`` and ``Duration`` are
+the most commonly used, and the default is ``Iteration``.
 
-after you select the type of scenario( such as Ping), you will select one type of runner, there are 4 types of runner. Usually, we use the "Iteration" and "Duration". and Default is "Iteration".
-For Iteration, you can specify the iteration number and interval of iteration. ::
+For ``Iteration``, you can specify the iteration number and interval of iteration. ::
 
   runner:
     type: Iteration
     iterations: 10
     interval: 1
 
-That means yardstick will iterate the 10 times of Ping test and the interval of each iteration is one second.
+That means Yardstick will repeat the Ping test 10 times and the interval of
+each iteration is one second.
 
-For Duration, you can specify the duration of this scenario and the interval of each ping test. ::
+For ``Duration``, you can specify the duration of this scenario and the
+interval of each ping test. ::
 
   runner:
     type: Duration
     duration: 60
     interval: 10
 
-That means yardstick will run the ping test as loop until the total time of this scenario reach the 60s and the interval of each loop is ten seconds.
-
+That means Yardstick will run the ping test as loop until the total time of
+this scenario reaches 60s and the interval of each loop is ten seconds.
 
-SLA is the criterion of this scenario. that depends on the scenario. different scenario can have different SLA metric.
 
+SLA is the criterion of this scenario. This depends on the scenario. Different
+scenarios can have different SLA metric.
 
-**How to write a new test case**
 
-Yardstick already provide a library of testing step. that means yardstick provide lots of type scenario.
+How to write a new test case
+++++++++++++++++++++++++++++
 
-Basiclly, What you need to do is to orchestrate the scenario from the library.
+Yardstick already provides a library of testing steps (i.e. different types of
+scenario).
 
-Here, We will show two cases. One is how to write a simple test case, the other is how to write a quite complex test case.
+Basically, what you need to do is to orchestrate the scenario from the library.
 
+Here, we will show two cases. One is how to write a simple test case, the other
+is how to write a quite complex test case.
 
 Write a new simple test case
+''''''''''''''''''''''''''''
 
 First, you can image a basic test case description as below.
 
@@ -314,7 +383,7 @@ First, you can image a basic test case description as below.
 TODO
 
 How can I contribute to Yardstick?
------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 If you are already a contributor of any OPNFV project, you can contribute to
 Yardstick. If you are totally new to OPNFV, you must first create your Linux
@@ -329,7 +398,7 @@ We distinguish 2 levels of contributors:
 Yardstick commitors are promoted by the Yardstick contributors.
 
 Gerrit & JIRA introduction
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+++++++++++++++++++++++++++
 
 .. _Gerrit: https://www.gerritcodereview.com/
 .. _`OPNFV Gerrit`: http://gerrit.opnfv.org/
@@ -338,7 +407,8 @@ Gerrit & JIRA introduction
 
 OPNFV uses Gerrit_ for web based code review and repository management for the
 Git Version Control System. You can access `OPNFV Gerrit`_. Please note that
-you need to have Linux Foundation ID in order to use OPNFV Gerrit. You can get one from this link_.
+you need to have Linux Foundation ID in order to use OPNFV Gerrit. You can get
+one from this link_.
 
 OPNFV uses JIRA_ for issue management. An important principle of change
 management is to have two-way trace-ability between issue management
@@ -350,14 +420,16 @@ If you want to contribute to Yardstick, you can pick a issue from Yardstick's
 JIRA dashboard or you can create you own issue and submit it to JIRA.
 
 Install Git and Git-reviews
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++++++++++++++++++++++++++++
 
 Installing and configuring Git and Git-Review is necessary in order to submit
-code to Gerrit. The `Getting to the code <https://wiki.opnfv.org/display/DEV/Developer+Getting+Started>`_ page will provide you with some help for that.
+code to Gerrit. The
+`Getting to the code <https://wiki.opnfv.org/display/DEV/Developer+Getting+Started>`_
+page will provide you with some help for that.
 
 
 Verify your patch locally before submitting
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++++++++++++++++++++++++++++++++++++++++++++
 
 Once you finish a patch, you can submit it to Gerrit for code review. A
 developer sends a new patch to Gerrit will trigger patch verify job on Jenkins
@@ -366,7 +438,8 @@ code coverage test. Before you submit your patch, it is recommended to run the
 patch verification in your local environment first.
 
 Open a terminal window and set the project's directory to the working
-directory using the ``cd`` command. Assume that ``YARDSTICK_REPO_DIR`` is the path to the Yardstick project folder on your computer::
+directory using the ``cd`` command. Assume that ``YARDSTICK_REPO_DIR`` is the
+path to the Yardstick project folder on your computer::
 
   cd $YARDSTICK_REPO_DIR
 
@@ -377,7 +450,7 @@ Verify your patch::
 It is used in CI but also by the CLI.
 
 Submit the code with Git
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+++++++++++++++++++++++++
 
 Tell Git which files you would like to take into account for the next commit.
 This is called 'staging' the files, by placing them into the staging area,
@@ -417,7 +490,7 @@ to the commits, and eventually navigate among the latter more easily.
 `This document`_ happened to be very clear and useful to get started with that.
 
 Push the code to Gerrit for review
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+++++++++++++++++++++++++++++++++++
 
 Now that the code has been comitted into your local Git repository the
 following step is to push it online to Gerrit for it to be reviewed. The
@@ -432,27 +505,27 @@ Yardstick committers and contributors to review your codes.
    :width: 800px
    :alt: Gerrit for code review
 
-You can find a list Yardstick people `here <https://wiki.opnfv.org/display/yardstick/People>`_,
-or use the ``yardstick-reviewers`` and ``yardstick-committers`` groups in gerrit.
+You can find a list Yardstick people
+`here <https://wiki.opnfv.org/display/yardstick/People>`_, or use the
+``yardstick-reviewers`` and ``yardstick-committers`` groups in gerrit.
 
 Modify the code under review in Gerrit
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+++++++++++++++++++++++++++++++++++++++
 
 At the same time the code is being reviewed in Gerrit, you may need to edit it
 to make some changes and then send it back for review. The following steps go
 through the procedure.
 
 Once you have modified/edited your code files under your IDE, you will have to
-stage them. The 'status' command is very helpful at this point as it provides
-an overview of Git's current state::
+stage them. The ``git status`` command is very helpful at this point as it
+provides an overview of Git's current state::
 
   git status
 
-The output of the command provides us with the files that have been modified
-after the latest commit.
+This command lists the files that have been modified since the last commit.
 
 You can now stage the files that have been modified as part of the Gerrit code
-review edition/modification/improvement using ``git add`` command. It is now
+review addition/modification/improvement using ``git add`` command. It is now
 time to commit the newly modified files, but the objective here is not to
 create a new commit, we simply want to inject the new changes into the
 previous commit. You can achieve that with the '--amend' option on the
@@ -469,7 +542,8 @@ The final step consists in pushing the newly modified commit to Gerrit::
 
 
 Plugins
-==========
+-------
 
-For information about Yardstick plugins, refer to the chapter **Installing a plug-in into Yardstick** in the `user guide`_.
+For information about Yardstick plugins, refer to the chapter
+**Installing a plug-in into Yardstick** in the `user guide`_.
 
index 2262841..7999005 100755 (executable)
@@ -244,10 +244,13 @@ Now let's examine the components of the file in detail
 3. ``nodes`` - This names the Traffic Generator and the System
    under Test. Does not need to change.
 
-4. ``prox_path`` - Location of the Prox executable on the traffic
+4. ``interface_speed_gbps`` - This is an optional parameter. If not present
+   the system defaults to 10Gbps. This defines the speed of the interfaces.
+
+5. ``prox_path`` - Location of the Prox executable on the traffic
    generator (Either baremetal or Openstack Virtual Machine)
 
-5. ``prox_config`` - This is the ``SUT Config File``.
+6. ``prox_config`` - This is the ``SUT Config File``.
    In this case it is ``handle_l2fwd-2.cfg``
 
    A number of additional parameters can be added. This example
@@ -285,16 +288,31 @@ Now let's examine the components of the file in detail
    of a file called ``parameters.lua``, which contains information
    retrieved from either the hardware or the openstack configuration.
 
-6. ``prox_args`` - this specifies the command line arguments to start
+7. ``prox_args`` - this specifies the command line arguments to start
    prox. See `prox command line`_.
 
-7. ``prox_config`` - This specifies the Traffic Generator config file.
+8. ``prox_config`` - This specifies the Traffic Generator config file.
+
+9. ``runner`` - This is set to ``ProxDuration`` - This specifies that the
+   test runs for a set duration. Other runner types are available
+   but it is recommend to use ``ProxDuration``
+
+   The following parrameters are supported
+
+   ``interval`` - (optional) - This specifies the sampling interval.
+   Default is 1 sec
+
+   ``sampled`` - (optional) - This specifies if sampling information is
+   required. Default ``no``
+
+   ``duration`` - This is the length of the test in seconds. Default
+   is 60 seconds.
 
-8. ``runner`` - This is set to ``Duration`` - This specified that the
-   test run for a set duration. Other runner types are available
-   but it is recommend to use ``Duration``
+   ``confirmation`` - This specifies the number of confirmation retests to
+   be made before deciding to increase or decrease line speed. Default 0.
+
+10. ``context`` - This is ``context`` for a 2 port Baremetal configuration.
 
-9. ``context`` - This is ``context`` for a 2 port Baremetal configuration.
    If a 4 port configuration was required then file
    ``prox-baremetal-4.yaml`` would be used. This is the NSB Prox
    baremetal configuration file.
@@ -304,7 +322,8 @@ Now let's examine the components of the file in detail
 *Traffic Profile file*
 ----------------------
 
-This describes the details of the traffic flow. In this case ``prox_binsearch.yaml`` is used.
+This describes the details of the traffic flow. In this case
+``prox_binsearch.yaml`` is used.
 
 .. image:: images/PROX_Traffic_profile.png
    :width: 800px
@@ -326,21 +345,29 @@ This describes the details of the traffic flow. In this case ``prox_binsearch.ya
 
    Custom traffic types can be created by creating a new traffic profile class.
 
-3. ``tolerated_loss`` - This specifies the percentage of packets that can be lost/dropped before
-   we declare success or failure. Success is Transmitted-Packets from Traffic Generator is greater than or equal to
+3. ``tolerated_loss`` - This specifies the percentage of packets that
+   can be lost/dropped before
+   we declare success or failure. Success is Transmitted-Packets from
+   Traffic Generator is greater than or equal to
    packets received by Traffic Generator plus tolerated loss.
 
-4. ``test_precision`` - This specifies the precision of the test results. For some tests the success criteria
-   may never be achieved because the test precision may be greater than the successful throughput. For finer
-   results increase the precision by making this value smaller.
+4. ``test_precision`` - This specifies the precision of the test
+   results. For some tests the success criteria may never be
+   achieved because the test precision may be greater than the
+   successful throughput. For finer results increase the precision
+   by making this value smaller.
 
-5. ``packet_sizes`` - This specifies the range of packets size this test is run for.
+5. ``packet_sizes`` - This specifies the range of packets size this
+   test is run for.
 
-6. ``duration`` - This specifies the sample duration that the test uses to check for success or failure.
+6. ``duration`` - This specifies the sample duration that the test
+   uses to check for success or failure.
 
-7. ``lower_bound`` - This specifies the test initial lower bound sample rate. On success this value is increased.
+7. ``lower_bound`` - This specifies the test initial lower bound sample rate.
+   On success this value is increased.
 
-8. ``upper_bound`` - This specifies the test initial upper bound sample rate. On success this value is decreased.
+8. ``upper_bound`` - This specifies the test initial upper bound sample rate.
+   On success this value is decreased.
 
 Other traffic profiles exist eg prox_ACL.yaml which does not
 compare what is received with what is transmitted. It just
@@ -371,14 +398,18 @@ See this prox_vpe.yaml as example::
 We will use ``tc_prox_heat_context_l2fwd-2.yaml`` as a example to show
 you how to understand the test description file.
 
-.. image:: images/PROX_Test_HEAT_Script.png
+.. image:: images/PROX_Test_HEAT_Script1.png
    :width: 800px
-   :alt: NSB PROX Test Description File
+   :alt: NSB PROX Test Description File - Part 1
+
+.. image:: images/PROX_Test_HEAT_Script2.png
+   :width: 800px
+   :alt: NSB PROX Test Description File - Part 2
 
 Now lets examine the components of the file in detail
 
-Sections 1 to 8 are exactly the same in Baremetal and in Heat. Section
-``9`` is replaced with sections A to F. Section 9 was for a baremetal
+Sections 1 to 9 are exactly the same in Baremetal and in Heat. Section
+``10`` is replaced with sections A to F. Section 10 was for a baremetal
 configuration file. This has no place in a heat configuration.
 
 A. ``image`` - yardstick-samplevnfs. This is the name of the image
@@ -418,12 +449,12 @@ F. ``networks`` - is composed of a management network labeled ``mgmt``
         gateway_ip: 'null'
         port_security_enabled: False
         enable_dhcp: 'false'
-      downlink_1:
+      uplink_1:
         cidr: '10.0.4.0/24'
         gateway_ip: 'null'
         port_security_enabled: False
         enable_dhcp: 'false'
-      downlink_2:
+      downlink_1:
         cidr: '10.0.5.0/24'
         gateway_ip: 'null'
         port_security_enabled: False
@@ -1033,7 +1064,7 @@ If PROX NSB does not work on baremetal, problem is either in network configurati
      1. What is received on 0 is transmitted on 1, received on 1 transmitted on 0,
         received on 2 transmitted on 3 and received on 3 transmitted on 2.
      2. No packets are Failed.
-     3. No Packets are discarded.
+     3. No packets are discarded.
 
   We can also dump the packets being received or transmitted via the following commands. ::
 
@@ -1228,7 +1259,69 @@ Where
     4) ir.intel.com = local no proxy
 
 
+*How to Understand the Grafana output?*
+---------------------------------------
+
+         .. image:: images/PROX_Grafana_1.png
+            :width: 1000px
+            :alt: NSB PROX Grafana_1
+
+         .. image:: images/PROX_Grafana_2.png
+            :width: 1000px
+            :alt: NSB PROX Grafana_2
+
+         .. image:: images/PROX_Grafana_3.png
+            :width: 1000px
+            :alt: NSB PROX Grafana_3
+
+         .. image:: images/PROX_Grafana_4.png
+            :width: 1000px
+            :alt: NSB PROX Grafana_4
+
+A. Test Parameters - Test interval, Duartion, Tolerated Loss and Test Precision
+
+B. Overall No of packets send and received during test
+
+C. Generator Stats - packets sent, received and attempted by Generator
+
+D. Packets Size
+
+E. No of packets received by SUT
+
+F. No of packets forwarded by SUT
+
+G. This is the number of packets sent by the generator per port, for each interval.
+
+H. This is the number of packets received by the generator per port, for each interval.
+
+I. This is the number of packets send and received by the generator and lost by the SUT
+   that meet the success criteria
+
+J. This is the changes the Percentage of Line Rate used over a test, The MAX and the
+   MIN should converge to within the interval specified as the ``test-precision``.
+
+K. This is the packets Size supported during test. If "N/A" appears in any field the result has not been decided.
+
+L. This is the calculated throughput in MPPS(Million Packets Per second) for this line rate.
+
+M. This is the actual No, of packets sent by the generator in MPPS
+
+N. This is the actual No. of packets received by the generator in MPPS
+
+O. This is the total No. of packets sent by SUT.
+
+P. This is the total No. of packets received by the SUT
+
+Q. This is the total No. of packets dropped. (These packets were sent by the generator but not
+   received back by the generator, these may be dropped by the SUT or the Generator)
+
+R. This is the tolerated no of packets that can be dropped.
+
+S. This is the test Throughput in Gbps
+
+T. This is the Latencey per Port
 
+U. This is the CPU Utilization
 
 
 
diff --git a/docs/testing/developer/devguide/images/PROX_Grafana_1.png b/docs/testing/developer/devguide/images/PROX_Grafana_1.png
new file mode 100644 (file)
index 0000000..d272edc
Binary files /dev/null and b/docs/testing/developer/devguide/images/PROX_Grafana_1.png differ
diff --git a/docs/testing/developer/devguide/images/PROX_Grafana_2.png b/docs/testing/developer/devguide/images/PROX_Grafana_2.png
new file mode 100644 (file)
index 0000000..4f7fd4c
Binary files /dev/null and b/docs/testing/developer/devguide/images/PROX_Grafana_2.png differ
diff --git a/docs/testing/developer/devguide/images/PROX_Grafana_3.png b/docs/testing/developer/devguide/images/PROX_Grafana_3.png
new file mode 100644 (file)
index 0000000..5ae9676
Binary files /dev/null and b/docs/testing/developer/devguide/images/PROX_Grafana_3.png differ
diff --git a/docs/testing/developer/devguide/images/PROX_Grafana_4.png b/docs/testing/developer/devguide/images/PROX_Grafana_4.png
new file mode 100644 (file)
index 0000000..5353d1c
Binary files /dev/null and b/docs/testing/developer/devguide/images/PROX_Grafana_4.png differ
index 32530eb..c09f7bb 100644 (file)
Binary files a/docs/testing/developer/devguide/images/PROX_Test_BM_Script.png and b/docs/testing/developer/devguide/images/PROX_Test_BM_Script.png differ
diff --git a/docs/testing/developer/devguide/images/PROX_Test_HEAT_Script.png b/docs/testing/developer/devguide/images/PROX_Test_HEAT_Script.png
deleted file mode 100644 (file)
index 754973b..0000000
Binary files a/docs/testing/developer/devguide/images/PROX_Test_HEAT_Script.png and /dev/null differ
diff --git a/docs/testing/developer/devguide/images/PROX_Test_HEAT_Script1.png b/docs/testing/developer/devguide/images/PROX_Test_HEAT_Script1.png
new file mode 100644 (file)
index 0000000..bd375db
Binary files /dev/null and b/docs/testing/developer/devguide/images/PROX_Test_HEAT_Script1.png differ
diff --git a/docs/testing/developer/devguide/images/PROX_Test_HEAT_Script2.png b/docs/testing/developer/devguide/images/PROX_Test_HEAT_Script2.png
new file mode 100644 (file)
index 0000000..99d9d24
Binary files /dev/null and b/docs/testing/developer/devguide/images/PROX_Test_HEAT_Script2.png differ
index 92a18f6..9a76a32 100644 (file)
@@ -14,3 +14,4 @@ Yardstick Developer Guide
    :numbered:
 
    devguide
+   devguide_nsb_prox
index 2e74182..a5f3a0c 100644 (file)
@@ -84,6 +84,116 @@ In this example we have ``TRex xe0 <-> xe0 VNF xe1 <-> xe0 UDP_Replay``
           downlink_0:
            - xe0
 
+
+Availability zone
+^^^^^^^^^^^^^^^^^
+
+The configuration of the availability zone is requred in cases where location
+of exact compute host/group of compute hosts needs to be specified for SampleVNF
+or traffic generator in the heat test case. If this is the case, please follow
+the instructions below.
+
+.. _`Create a host aggregate`:
+
+1. Create a host aggregate in the OpenStack and add the available compute hosts
+   into the aggregate group.
+
+   .. note:: Change the ``<AZ_NAME>`` (availability zone name), ``<AGG_NAME>``
+     (host aggregate name) and ``<HOST>`` (host name of one of the compute) in the
+     commands below.
+
+   .. code-block:: bash
+
+     # create host aggregate
+     openstack aggregate create --zone <AZ_NAME> --property availability_zone=<AZ_NAME> <AGG_NAME>
+     # show available hosts
+     openstack compute service list --service nova-compute
+     # add selected host into the host aggregate
+     openstack aggregate add host <AGG_NAME> <HOST>
+
+2. To specify the OpenStack location (the exact compute host or group of the hosts)
+   of SampleVNF or traffic generator in the heat test case, the ``availability_zone`` server
+   configuration option should be used. For example:
+
+   .. note:: The ``<AZ_NAME>`` (availability zone name) should be changed according
+     to the name used during the host aggregate creation steps above.
+
+   .. code-block:: yaml
+
+     context:
+       name: yardstick
+       image: yardstick-samplevnfs
+       ...
+       servers:
+         vnf__0:
+           ...
+           availability_zone: <AZ_NAME>
+           ...
+         tg__0:
+           ...
+           availability_zone: <AZ_NAME>
+           ...
+       networks:
+         ...
+
+There are two example of SampleVNF scale out test case which use the availability zone
+feature to specify the exact location of scaled VNFs and traffic generators.
+
+Those are:
+
+.. code-block:: console
+
+  <repo>/samples/vnf_samples/nsut/prox/tc_prox_heat_context_l2fwd_multiflow-2-scale-out.yaml
+  <repo>/samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_64B_trex_scale_out.yaml
+
+.. note:: This section describes the PROX scale-out testcase, but the same
+  procedure is used for the vFW test case.
+
+1. Before running the scale-out test case, make sure the host aggregates are
+   configured in the OpenStack environment. To check this, run the following
+   command:
+
+   .. code-block:: console
+
+     # show configured host aggregates (example)
+     openstack aggregate list
+     +----+------+-------------------+
+     | ID | Name | Availability Zone |
+     +----+------+-------------------+
+     |  4 | agg0 | AZ_NAME_0         |
+     |  5 | agg1 | AZ_NAME_1         |
+     +----+------+-------------------+
+
+2. If no host aggregates are configured, please use `steps above`__ to
+   configure them.
+
+__ `Create a host aggregate`_
+
+
+3. Run the SampleVNF PROX scale-out test case, specifying the availability
+   zone of each VNF and traffic generator as a task arguments.
+
+   .. note:: The ``az_0`` and ``az_1`` should be changed according to the host
+     aggregates created in the OpenStack.
+
+   .. code-block:: console
+
+     yardstick -d task start\
+     <repo>/samples/vnf_samples/nsut/prox/tc_prox_heat_context_l2fwd_multiflow-2-scale-out.yaml\
+       --task-args='{
+         "num_vnfs": 4, "availability_zone": {
+           "vnf_0": "az_0", "tg_0": "az_1",
+           "vnf_1": "az_0", "tg_1": "az_1",
+           "vnf_2": "az_0", "tg_2": "az_1",
+           "vnf_3": "az_0", "tg_3": "az_1"
+         }
+       }'
+
+   ``num_vnfs`` specifies how many VNFs are going to be deployed in the
+   ``heat`` contexts. ``vnf_X`` and ``tg_X`` arguments configure the
+   availability zone where the VNF and traffic generator is going to be deployed.
+
+
 Collectd KPIs
 -------------
 
@@ -154,7 +264,7 @@ We set the VCPUs and memory using the ``--task-args`` options
 
 .. code-block:: console
 
-  yardstick task start --task-args='{"mem": 10480, "vcpus": 4, "ports": 2}' \
+  yardstick task start --task-args='{"mem": 10480, "vcpus": 4, "vports": 2}' \
   samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_64B_trex_scale-up.yaml
 
 In order to support ports scale-up, traffic and topology templates need to be used in testcase.
@@ -242,7 +352,7 @@ Baremetal
        file: /etc/yardstick/nodes/pod.yaml
 
 Scale-Out
---------------------
+---------
 
 VNFs performance data with scale-out helps
 
@@ -313,3 +423,39 @@ options section.
       options:
         tg_0:
           queues_per_port: 2
+
+
+Standalone configuration
+------------------------
+
+NSB supports certain Standalone deployment configurations.
+Standalone supports provisioning a VM in a standalone visualised environment using kvm/qemu.
+There two types of Standalone contexts available: OVS-DPDK and SRIOV.
+OVS-DPDK uses OVS network with DPDK drivers.
+SRIOV enables network traffic to bypass the software switch layer of the Hyper-V stack.
+
+Standalone with OVS-DPDK
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+SampleVNF image is spawned in a VM on a baremetal server.
+OVS with DPDK is installed on the baremetal server.
+
+.. note:: Ubuntu 17.10 requires DPDK v.17.05 and higher, DPDK v.17.05 requires OVS v.2.8.0.
+
+Default values for OVS-DPDK:
+
+  * queues: 4
+  * lcore_mask: ""
+  * pmd_cpu_mask: "0x6"
+
+Sample test case file
+^^^^^^^^^^^^^^^^^^^^^
+
+  1. Prepare SampleVNF image and copy it to ``flavor/images``.
+  2. Prepare context files for TREX and SampleVNF under ``contexts/file``.
+  3. Add bridge named ``br-int`` to the baremetal where SampleVNF image is deployed.
+  4. Modify ``networks/phy_port`` accordingly to the baremetal setup.
+  5. Run test from:
+
+.. literalinclude:: /submodules/yardstick/samples/vnf_samples/nsut/acl/tc_ovs_rfc2544_ipv4_1rule_1flow_64B_trex.yaml
+   :language: yaml
index 86796c4..1f53449 100755 (executable)
@@ -63,7 +63,7 @@ for i in "${pkg[@]}"; do
     fi
 done
 
-pip install ansible==2.4.2 shade==1.22.2 docker-py==1.10.6
+pip install ansible==2.5.5 shade==1.22.2 docker-py==1.10.6
 
 ANSIBLE_SCRIPTS="ansible"
 
@@ -79,4 +79,4 @@ ansible-playbook \
          -e img_property="nsb" \
          ${yardstick_docker_image} \
          -e YARD_IMG_ARCH='amd64' ${extra_args}\
-         -i yardstick-install-inventory.ini nsb_setup.yml
+         -i install-inventory.ini nsb_setup.yml
index 60014d7..43d7120 100644 (file)
@@ -11,7 +11,7 @@ Babel==2.3.4            # BSD; OSI Approved  BSD License
 Jinja2==2.9.6           # BSD; OSI Approved  BSD License
 SQLAlchemy==1.1.12      # MIT License; OSI Approved  MIT License
 PTable==0.9.2           # BSD (3 clause); OSI Approved  BSD License
-ansible==2.4.2          # GPLv3; OSI Approved  GNU General Public License v3 or later (GPLv3+)
+ansible==2.5.5          # GPLv3; OSI Approved  GNU General Public License v3 or later (GPLv3+)
 backport-ipaddress==0.1; python_version <= "2.7"    # OSI Approved  Python Software Foundation License
 chainmap==1.0.2         # Python Software Foundation License; OSI Approved  Python Software Foundation License
 cmd2==0.8.6             # MIT License; OSI Approved  MIT License
@@ -29,20 +29,20 @@ futures==3.1.1;python_version=='2.7'    # BSD; OSI Approved  BSD License
 influxdb==4.1.1         # MIT License; OSI Approved  MIT License
 IxNetwork==8.40.1124.9  # MIT License; OSI Approved  MIT License
 jinja2schema==0.1.4     # OSI Approved  BSD License
-keystoneauth1==3.1.0    # OSI Approved  Apache Software License
+keystoneauth1==3.3.0    # OSI Approved  Apache Software License
 kubernetes==6.0.0       # OSI Approved  Apache Software License
 mock==2.0.0             # OSI Approved  BSD License; `BSD License`_; http://github.com/testing-cabal/mock/blob/master/LICENSE.txt
 msgpack-python==0.4.8   # OSI Approved  Apache Software License
 netaddr==0.7.19         # BSD License; OSI Approved  BSD License; OSI Approved  MIT License
 netifaces==0.10.6       # MIT License; OSI Approved  MIT License
 os-client-config==1.28.0    # OSI Approved  Apache Software License
-osc-lib==1.7.0          # OSI Approved  Apache Software License
-oslo.config==4.11.1     # OSI Approved  Apache Software License
+osc-lib==1.8.0          # OSI Approved  Apache Software License
+oslo.config==5.1.0     # OSI Approved  Apache Software License
 oslo.i18n==3.17.0       # OSI Approved  Apache Software License
-oslo.messaging===5.36.0 # OSI Approved  Apache Software License
-oslo.privsep===1.22.1   # OSI Approved  Apache Software License
+oslo.messaging==5.36.0 # OSI Approved  Apache Software License
+oslo.privsep==1.23.0   # OSI Approved  Apache Software License
 oslo.serialization==2.20.1  # OSI Approved  Apache Software License
-oslo.utils==3.28.0      # OSI Approved  Apache Software License
+oslo.utils==3.33.0      # OSI Approved  Apache Software License
 paramiko==2.2.1         # LGPL; OSI Approved  GNU Library or Lesser General Public License (LGPL)
 pbr==3.1.1              # OSI Approved  Apache Software License; Apache License, Version 2.0
 pika==0.10.0            # BSD; OSI Approved  BSD License
@@ -52,13 +52,13 @@ pycrypto==2.6.1         # Public Domain
 pyparsing==2.2.0        # MIT License; OSI Approved  MIT License
 pyroute2==0.4.21        # dual license GPLv2+ and Apache v2; OSI Approved  GNU General Public License v2 or later (GPLv2+); OSI Approved  Apache Software License
 pyrsistent==0.14.1      # LICENSE.mit; OSI Approved  MIT License
-python-cinderclient==3.1.0      # OSI Approved  Apache Software License
+python-cinderclient==3.3.0      # OSI Approved  Apache Software License
 python-glanceclient==2.8.0      # OSI Approved  Apache Software License
 python-keystoneclient==3.13.0   # OSI Approved  Apache Software License
 python-neutronclient==6.5.0     # OSI Approved  Apache Software License
 python-novaclient==9.1.1        # OSI Approved  Apache Software License
 pyzmq==16.0.2           # LGPL+BSD; OSI Approved  GNU Library or Lesser General Public License (LGPL); OSI Approved  BSD License
-requests==2.11.1        # Apache 2.0; OSI Approved  Apache Software License
+requests==2.14.2        # Apache 2.0; OSI Approved  Apache Software License
 requestsexceptions==1.3.0   # OSI Approved  Apache Software License
 scp==0.10.2             # LGPL
 shade==1.22.2           # OSI Approved  Apache Software License
index b184a29..49066e9 100644 (file)
 # 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.
-
-access-list1:
-  acl:
-    access-list-entries:
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 152.16.40.20/24
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 0.0.0.0/0
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1588
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 0.0.0.0/0
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 152.16.100.20/24
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1589
-    acl-name: sample-ipv4-acl
-    acl-type: ipv4-acl
+---
+access-list-entries:
+  -
+    actions: [drop,count]
+    matches:
+      destination-ipv4-network: 152.16.40.20/24
+      destination-port-range:
+        lower-port: 0
+        upper-port: 65535
+      source-ipv4-network: 0.0.0.0/0
+      source-port-range:
+        lower-port: 0
+        upper-port: 65535
+    rule-name: rule1588
+  -
+    actions: [drop,count]
+    matches:
+      destination-ipv4-network: 0.0.0.0/0
+      destination-port-range:
+        lower-port: 0
+        upper-port: 65535
+      source-ipv4-network: 152.16.100.20/24
+      source-port-range:
+        lower-port: 0
+        upper-port: 65535
+    rule-name: rule1589
index b184a29..49066e9 100644 (file)
 # 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.
-
-access-list1:
-  acl:
-    access-list-entries:
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 152.16.40.20/24
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 0.0.0.0/0
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1588
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 0.0.0.0/0
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 152.16.100.20/24
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1589
-    acl-name: sample-ipv4-acl
-    acl-type: ipv4-acl
+---
+access-list-entries:
+  -
+    actions: [drop,count]
+    matches:
+      destination-ipv4-network: 152.16.40.20/24
+      destination-port-range:
+        lower-port: 0
+        upper-port: 65535
+      source-ipv4-network: 0.0.0.0/0
+      source-port-range:
+        lower-port: 0
+        upper-port: 65535
+    rule-name: rule1588
+  -
+    actions: [drop,count]
+    matches:
+      destination-ipv4-network: 0.0.0.0/0
+      destination-port-range:
+        lower-port: 0
+        upper-port: 65535
+      source-ipv4-network: 152.16.100.20/24
+      source-port-range:
+        lower-port: 0
+        upper-port: 65535
+    rule-name: rule1589
index b184a29..6f09bb8 100644 (file)
 # 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.
-
-access-list1:
-  acl:
-    access-list-entries:
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 152.16.40.20/24
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 0.0.0.0/0
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1588
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 0.0.0.0/0
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 152.16.100.20/24
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1589
-    acl-name: sample-ipv4-acl
-    acl-type: ipv4-acl
+---
+access-list-entries:
+  -
+    ace-oper-data:
+      match-counter: 0
+    actions: [drop,count]
+    matches:
+      destination-ipv4-network: 152.16.40.20/24
+      destination-port-range:
+        lower-port: 0
+        upper-port: 65535
+      source-ipv4-network: 0.0.0.0/0
+      source-port-range:
+        lower-port: 0
+        upper-port: 65535
+    rule-name: rule1588
+  -
+    ace-oper-data:
+      match-counter: 0
+    actions: [drop,count]
+    matches:
+      destination-ipv4-network: 0.0.0.0/0
+      destination-port-range:
+        lower-port: 0
+        upper-port: 65535
+      source-ipv4-network: 152.16.100.20/24
+      source-port-range:
+        lower-port: 0
+        upper-port: 65535
+    rule-name: rule1589
index 134b15f..00bd186 100644 (file)
@@ -42,10 +42,10 @@ scenarios:
 contexts:
    - name: yardstick
      type: Node
-     file: /etc/yardstick/nodes/standalone/pod_trex.yaml
+     file: etc/yardstick/nodes/standalone/pod_trex.yaml
    - type: StandaloneOvsDpdk
      name: yardstick
-     file: /etc/yardstick/nodes/standalone/pod_ovs.yaml
+     file: etc/yardstick/nodes/standalone/host_ovs.yaml
      vm_deploy: True
      ovs_properties:
        version:
@@ -56,10 +56,12 @@ contexts:
          socket_0: 2048
          socket_1: 2048
        queues: 4
+       lcore_mask: ""
+       pmd_cpu_mask: "0x6"
        vpath: "/usr/local"
 
      flavor:
-       images: "/var/lib/libvirt/images/ubuntu.qcow2"
+       images: "/var/lib/libvirt/images/yardstick-nsb-image.img"
        ram: 4096
        extra_specs:
          hw:cpu_sockets: 1
index 3b9c68f..a70ea65 100644 (file)
@@ -56,7 +56,7 @@ mode=gen
 tx port=cpe0
 bps=12500000
 ; Ethernet + QinQ + ARP-reply
-pkt inline=${sut_mac0} 70 00 00 00 00 01 ${qinq_tag_inline} 00 01 81 00 00 01 08 06 00 01 08 00 06 04 00 02 00 1e 67 3e b8 df c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 01
+pkt inline=${sut_mac0} 00 00 02 00 00 02 ${qinq_tag_inline} 00 01 81 00 00 01 08 06 00 01 08 00 06 04 00 02 00 1e 67 3e b8 df c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 01
 ; svlan: [0..127]
 random=000000000XXXXXXX
 rand_offset=14
@@ -71,7 +71,7 @@ mode=gen
 tx port=cpe1
 bps=12500000
 ; Ethernet + QinQ + ARP-reply
-pkt inline=${sut_mac2} 70 00 00 00 00 03 ${qinq_tag_inline} 00 01 81 00 00 01 08 06 00 01 08 00 06 04 00 02 00 1e 67 3e b8 df c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 01
+pkt inline=${sut_mac2} 00 00 02 00 00 02 ${qinq_tag_inline} 00 01 81 00 00 01 08 06 00 01 08 00 06 04 00 02 00 1e 67 3e b8 df c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 01
 ; svlan: [128..255]
 random=000000001XXXXXXX
 rand_offset=14
@@ -93,8 +93,8 @@ rand_offset=14
 ; cvlan: 256*[0..15]+16*[0..3]+[0..3]
 random=0000XXXX00XX00XX
 rand_offset=18
-; dst_ip: [10,11].[0..255].[0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240].[0..255]
-random=0000101XXXXXXXXXXXXX0000XXXXXXXX
+; dst_ip: [10,11].[odd 1..255].[16,48,80,112,144,176,208,240].[odd 1..255]
+random=0000101XXXXXXXX1XXX10000XXXXXXX1
 rand_offset=38
 lat pos=42
 
@@ -105,15 +105,15 @@ mode=gen
 tx port=cpe1
 bps=1069289928
 ; Ethernet + QinQ + IP + UDP
-pkt inline=${sut_mac2} 70 00 00 00 00 03 ${qinq_tag_inline} 00 01 81 00 00 01 08 00 45 00 00 1c 00 01 00 00 40 11 f7 7d c0 a8 01 01 c0 a8 01 01 00 35 00 35 00 08 7c 21
+pkt inline=${sut_mac2} 70 00 00 00 00 01 ${qinq_tag_inline} 00 01 81 00 00 01 08 00 45 00 00 1c 00 01 00 00 40 11 f7 7d c0 a8 01 01 c0 a8 01 01 00 35 00 35 00 08 7c 21
 ; svlan: [128..255]
 random=000000001XXXXXXX
 rand_offset=14
 ; cvlan: 256*[0..15]+16*[0..3]+[0..3]
 random=0000XXXX00XX00XX
 rand_offset=18
-; dst_ip: [10,11].[0..255].[0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240].[0..255]
-random=0000101XXXXXXXXXXXXX0000XXXXXXXX
+; dst_ip: [10,11].[odd 1..255].[16,48,80,112,144,176,208,240].[odd 1..255]
+random=0000101XXXXXXXX1XXX10000XXXXXXX1
 rand_offset=38
 lat pos=42
 
index 3b9c68f..a70ea65 100644 (file)
@@ -56,7 +56,7 @@ mode=gen
 tx port=cpe0
 bps=12500000
 ; Ethernet + QinQ + ARP-reply
-pkt inline=${sut_mac0} 70 00 00 00 00 01 ${qinq_tag_inline} 00 01 81 00 00 01 08 06 00 01 08 00 06 04 00 02 00 1e 67 3e b8 df c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 01
+pkt inline=${sut_mac0} 00 00 02 00 00 02 ${qinq_tag_inline} 00 01 81 00 00 01 08 06 00 01 08 00 06 04 00 02 00 1e 67 3e b8 df c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 01
 ; svlan: [0..127]
 random=000000000XXXXXXX
 rand_offset=14
@@ -71,7 +71,7 @@ mode=gen
 tx port=cpe1
 bps=12500000
 ; Ethernet + QinQ + ARP-reply
-pkt inline=${sut_mac2} 70 00 00 00 00 03 ${qinq_tag_inline} 00 01 81 00 00 01 08 06 00 01 08 00 06 04 00 02 00 1e 67 3e b8 df c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 01
+pkt inline=${sut_mac2} 00 00 02 00 00 02 ${qinq_tag_inline} 00 01 81 00 00 01 08 06 00 01 08 00 06 04 00 02 00 1e 67 3e b8 df c0 a8 01 01 00 00 00 00 00 00 c0 a8 01 01
 ; svlan: [128..255]
 random=000000001XXXXXXX
 rand_offset=14
@@ -93,8 +93,8 @@ rand_offset=14
 ; cvlan: 256*[0..15]+16*[0..3]+[0..3]
 random=0000XXXX00XX00XX
 rand_offset=18
-; dst_ip: [10,11].[0..255].[0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240].[0..255]
-random=0000101XXXXXXXXXXXXX0000XXXXXXXX
+; dst_ip: [10,11].[odd 1..255].[16,48,80,112,144,176,208,240].[odd 1..255]
+random=0000101XXXXXXXX1XXX10000XXXXXXX1
 rand_offset=38
 lat pos=42
 
@@ -105,15 +105,15 @@ mode=gen
 tx port=cpe1
 bps=1069289928
 ; Ethernet + QinQ + IP + UDP
-pkt inline=${sut_mac2} 70 00 00 00 00 03 ${qinq_tag_inline} 00 01 81 00 00 01 08 00 45 00 00 1c 00 01 00 00 40 11 f7 7d c0 a8 01 01 c0 a8 01 01 00 35 00 35 00 08 7c 21
+pkt inline=${sut_mac2} 70 00 00 00 00 01 ${qinq_tag_inline} 00 01 81 00 00 01 08 00 45 00 00 1c 00 01 00 00 40 11 f7 7d c0 a8 01 01 c0 a8 01 01 00 35 00 35 00 08 7c 21
 ; svlan: [128..255]
 random=000000001XXXXXXX
 rand_offset=14
 ; cvlan: 256*[0..15]+16*[0..3]+[0..3]
 random=0000XXXX00XX00XX
 rand_offset=18
-; dst_ip: [10,11].[0..255].[0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240].[0..255]
-random=0000101XXXXXXXXXXXXX0000XXXXXXXX
+; dst_ip: [10,11].[odd 1..255].[16,48,80,112,144,176,208,240].[odd 1..255]
+random=0000101XXXXXXXX1XXX10000XXXXXXX1
 rand_offset=38
 lat pos=42
 
index e602fac..7d350bd 100644 (file)
@@ -27,7 +27,7 @@ $core_lb_cpe0  =1
 $core_inet0    =2
 $core_lb_cpe1  =3
 $core_inet1    =4
-$core_workers  =13-14,15-16
+$core_workers  =13-14,15-16,17-18,19-20
 $core_tx_cpe0  =6
 $core_tx_cpe1  =8
 $core_tx_inet0 =9
index e1da4cd..f65b7cb 100644 (file)
@@ -28,7 +28,7 @@ $core_lb_cpe0  =1
 $core_inet0    =2
 $core_lb_cpe1  =3
 $core_inet1    =4
-$core_workers  =13-14,15-16 ;sut_bng_qos_wk
+$core_workers  =13-14,15-16,17-18,19-20
 $core_qos_cpe0 =5
 $core_tx_cpe0  =6
 $core_qos_cpe1 =7
index b4b0036..4b586b4 100644 (file)
@@ -38,32 +38,34 @@ nsd:nsd-catalog:
                 vnfd-id-ref: vnf__0
 
         -   id: downlink_0
-            name: vnf__0 to tg__0 link 1
+            name: vnf__0 to tg__0 link 2
             type: ELAN
             vnfd-connection-point-ref:
-            -   member-vnf-index-ref: '1'
+            -   member-vnf-index-ref: '2'
                 vnfd-connection-point-ref: xe1
                 vnfd-id-ref: vnf__0
-            -   member-vnf-index-ref: '2'
+            -   member-vnf-index-ref: '1'
                 vnfd-connection-point-ref: xe1
                 vnfd-id-ref: tg__0
-        -   id: downlink_1
-            name: vnf__0 to tg__0 link 2
+
+        -   id: uplink_1
+            name: tg__0 to vnf__0 link 3
             type: ELAN
             vnfd-connection-point-ref:
             -   member-vnf-index-ref: '1'
                 vnfd-connection-point-ref: xe2
-                vnfd-id-ref: vnf__0
+                vnfd-id-ref: tg__0
             -   member-vnf-index-ref: '2'
                 vnfd-connection-point-ref: xe2
-                vnfd-id-ref: tg__0
-        -   id: downlink_2
-            name: vnf__0 to tg__0 link 3
+                vnfd-id-ref: vnf__0
+
+        -   id: downlink_1
+            name: vnf__0 to tg__0 link 4
             type: ELAN
             vnfd-connection-point-ref:
-            -   member-vnf-index-ref: '1'
+            -   member-vnf-index-ref: '2'
                 vnfd-connection-point-ref: xe3
                 vnfd-id-ref: vnf__0
-            -   member-vnf-index-ref: '2'
+            -   member-vnf-index-ref: '1'
                 vnfd-connection-point-ref: xe3
                 vnfd-id-ref: tg__0
diff --git a/samples/vnf_samples/nsut/prox/prox-tg-topology-scale-out.yaml b/samples/vnf_samples/nsut/prox/prox-tg-topology-scale-out.yaml
new file mode 100644 (file)
index 0000000..5f01ecb
--- /dev/null
@@ -0,0 +1,53 @@
+# Copyright (c) 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.
+{% set num_vnfs = get(extra_args, 'num_vnfs', 1) %}
+---
+nsd:nsd-catalog:
+    nsd:
+    -   id: prox-tg-topology
+        name: prox-tg-topology
+        short-name: prox-tg-topology
+        description: prox-tg-topology
+        constituent-vnfd:
+{% for vnf_num in range(num_vnfs|int) %}
+        -   member-vnf-index: '{{ (vnf_num * 2) + 1 }}'
+            vnfd-id-ref: tg__{{ vnf_num }}
+            VNF model: ../../vnf_descriptors/tg_prox_tpl.yaml
+        -   member-vnf-index: '{{ (vnf_num * 2) + 2 }}'
+            vnfd-id-ref: vnf__{{ vnf_num }}
+            VNF model: ../../vnf_descriptors/prox_vnf.yaml
+{% endfor %}
+        vld:
+{% for vnf_num in range(num_vnfs|int) %}
+        -   id: uplink_{{ vnf_num }}
+            name: tg__{{ vnf_num }} to vnf__{{ vnf_num }} link {{ (vnf_num * 2) + 1 }}
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '{{ (vnf_num * 2) + 1 }}'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: tg__{{ vnf_num }}
+            -   member-vnf-index-ref: '{{ (vnf_num * 2) + 2 }}'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: vnf__{{ vnf_num }}
+        -   id: downlink_{{ vnf_num }}
+            name: vnf__{{ vnf_num }} to tg__{{ vnf_num }} link {{ (vnf_num * 2) + 2 }}
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '{{ (vnf_num * 2) + 1 }}'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: vnf__{{ vnf_num }}
+            -   member-vnf-index-ref: '{{ (vnf_num * 2) + 2 }}'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: tg__{{ vnf_num }}
+{% endfor %}
index 914bace..1711c56 100644 (file)
@@ -26,6 +26,9 @@ scenarios:
     vnf__0: vnf_0.yardstick
 
   options:
+
+    interface_speed_gbps: 10
+
     vnf__0:
       prox_path: /opt/nsb_bin/prox
       prox_config: "configs/handle_bng-4.cfg"
@@ -34,6 +37,7 @@ scenarios:
       prox_files:
         "configs/gre_table.lua" : ""
         "configs/ipv4.lua" : ""
+      prox_generate_parameter: True
 
     tg__0:
       prox_path: /opt/nsb_bin/prox
@@ -43,9 +47,12 @@ scenarios:
         "-t": ""
 
   runner:
-    type: Duration
+    type: ProxDuration
     # we kill after duration, independent of test duration, so set this high
-    duration: 300
+    duration: 2900
+    confirmation: 1
+    sampled: yes
+    interval: 1
 
 context:
   type: Node
index 599a6e0..a7d2d38 100644 (file)
@@ -26,6 +26,9 @@ scenarios:
     vnf__0: vnf_0.yardstick
 
   options:
+
+    interface_speed_gbps: 10
+
     vnf__0:
       prox_path: /opt/nsb_bin/prox
       prox_config: "configs/handle_bng_qos-4.cfg"
@@ -35,6 +38,7 @@ scenarios:
         "configs/gre_table.lua" : ""
         "configs/ipv4.lua" : ""
         "configs/dscp.lua" : ""
+      prox_generate_parameter: True
 
     tg__0:
       prox_path: /opt/nsb_bin/prox
@@ -44,9 +48,12 @@ scenarios:
         "-t": ""
 
   runner:
-    type: Duration
+    type: ProxDuration
     # we kill after duration, independent of test duration, so set this high
-    duration: 300
+    duration: 2900
+    confirmation: 1
+    sampled: yes
+    interval: 1
 
 context:
   type: Node
index ab067a8..84edcd4 100644 (file)
@@ -42,9 +42,15 @@ scenarios:
         "-t": ""
 
   runner:
-    type: Duration
+    type: ProxDuration
+    # sampling interval
+    interval: 1
+    # sampled : yes OR sampled: no (DEFAULT yes)
+    sampled: yes
     # we kill after duration, independent of test duration, so set this high
-    duration: 300
+    duration: 3100
+    # Confirmation attempts
+    confirmation: 1
 
 context:
   type: Node
index 16dfa1b..7b64f21 100644 (file)
@@ -47,9 +47,12 @@ scenarios:
         "-t": ""
 
   runner:
-    type: Duration
+    type: ProxDuration
     # we kill after duration, independent of test duration, so set this high
-    duration: 300
+    duration: 2900
+    confirmation: 1
+    sampled: yes
+    interval: 1
 
 context:
   type: Node
index ece618f..eaa9401 100644 (file)
@@ -91,12 +91,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
index 5e4ced1..0a07927 100644 (file)
@@ -88,14 +88,15 @@ context:
   networks:
     mgmt:
       cidr: '10.0.1.0/24'
-    uplink_0:
-      cidr: '10.0.2.0/24'
+{% for vport in range(1,vports,2|int) %}
+    uplink_{{ loop.index0 }}:
+      cidr: '10.0.{{ vport+1 }}.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-{% for vport in range(vports-1|int) %}
-    downlink_{{ vport }}:
-      cidr: '10.0.{{ vport+3 }}.0/24'
+
+    downlink_{{ loop.index0 }}:
+      cidr: '10.0.{{ vport+2 }}.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
index 67ad5e2..e4cd546 100644 (file)
@@ -26,6 +26,9 @@ scenarios:
     vnf__0: vnf_0.yardstick
 
   options:
+
+    interface_speed_gbps: 10
+
     vnf__0:
       prox_path: /opt/nsb_bin/prox
       prox_config: "configs/handle_bng-4.cfg"
@@ -34,6 +37,7 @@ scenarios:
       prox_files:
         "configs/gre_table.lua" : ""
         "configs/ipv4.lua" : ""
+      prox_generate_parameter: True
 
     tg__0:
       prox_path: /opt/nsb_bin/prox
@@ -45,14 +49,14 @@ scenarios:
   runner:
     type: Duration
     # we kill after duration, independent of test duration, so set this high
-    duration: 300
+    duration: 1600
 
 context:
   name: yardstick
   image: yardstick-samplevnfs
   user: ubuntu
   flavor:
-    vcpus: 18 
+    vcpus: 18
     ram: 20480
     disk: 6
     extra_specs:
@@ -85,12 +89,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
index 0578bf5..60002f0 100644 (file)
@@ -26,6 +26,9 @@ scenarios:
     vnf__0: vnf_0.yardstick
 
   options:
+
+    interface_speed_gbps: 10
+
     vnf__0:
       prox_path: /opt/nsb_bin/prox
       prox_config: "configs/handle_bng_qos-4.cfg"
@@ -35,6 +38,7 @@ scenarios:
         "configs/gre_table.lua" : ""
         "configs/ipv4.lua" : ""
         "configs/dscp.lua" : ""
+      prox_generate_parameter: True
 
     tg__0:
       prox_path: /opt/nsb_bin/prox
@@ -46,7 +50,7 @@ scenarios:
   runner:
     type: Duration
     # we kill after duration, independent of test duration, so set this high
-    duration: 300
+    duration: 1600
 
 context:
   name: yardstick
@@ -86,12 +90,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
index a0bc7ef..55f7943 100644 (file)
@@ -81,12 +81,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
diff --git a/samples/vnf_samples/nsut/prox/tc_prox_heat_context_l2fwd_multiflow-2-scale-out.yaml b/samples/vnf_samples/nsut/prox/tc_prox_heat_context_l2fwd_multiflow-2-scale-out.yaml
new file mode 100644 (file)
index 0000000..88581d2
--- /dev/null
@@ -0,0 +1,113 @@
+# Copyright (c) 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.
+{% set num_vnfs = num_vnfs or 1 %}
+{% set availability_zone = availability_zone or {} %}
+---
+schema: "yardstick:task:0.1"
+scenarios:
+-
+  type: NSPerf
+  traffic_profile: ../../traffic_profiles/prox_binsearch.yaml
+  topology: prox-tg-topology-scale-out.yaml
+  extra_args:
+    num_vnfs: {{ num_vnfs }}
+
+  nodes:
+{% for vnf_num in range(num_vnfs|int) %}
+    tg__{{ vnf_num }}: tg_{{ vnf_num }}.yardstick
+    vnf__{{ vnf_num }}: vnf_{{ vnf_num }}.yardstick
+{% endfor %}
+
+  options:
+{% for vnf_num in range(num_vnfs|int) %}
+    vnf__{{ vnf_num }}:
+      prox_path: /opt/nsb_bin/prox
+      prox_config: "configs/handle_l2fwd_multiflow-2.cfg"
+      prox_args:
+        "-t": ""
+
+    tg__{{ vnf_num }}:
+      prox_path: /opt/nsb_bin/prox
+      prox_config: "configs/gen_l2fwd_multiflow-2.cfg"
+      prox_args:
+        "-e": ""
+        "-t": ""
+{% endfor %}
+
+  runner:
+    type: Duration
+    # we kill after duration, independent of test duration, so set this high
+    duration: 300
+
+context:
+  name: yardstick
+  image: yardstick-samplevnfs
+  user: ubuntu
+  flavor:
+    vcpus: 8
+    ram: 20480
+    disk: 10
+    extra_specs:
+      hw:cpu_sockets: 1
+      hw:cpu_cores: 8
+      hw:cpu_threads: 1
+  placement_groups:
+    pgrp1:
+      policy: "availability"
+
+  servers:
+{% for vnf_num in range(num_vnfs|int) %}
+    vnf_{{ vnf_num }}:
+      floating_ip: true
+      placement: "pgrp1"
+      {% if 'vnf_%s'|format(vnf_num) in availability_zone %}
+      availability_zone: "{{ availability_zone['vnf_%s'|format(vnf_num)] }}"
+      {% endif %}
+      network_ports:
+        mgmt:
+          - mgmt
+        uplink_{{ vnf_num }}:
+          - xe0
+        downlink_{{ vnf_num }}:
+          - xe1
+    tg_{{ vnf_num }}:
+      floating_ip: true
+      placement: "pgrp1"
+      {% if 'tg_%s'|format(vnf_num) in availability_zone %}
+      availability_zone: "{{ availability_zone['tg_%s'|format(vnf_num)] }}"
+      {% endif %}
+      network_ports:
+        mgmt:
+          - mgmt
+        uplink_{{ vnf_num }}:
+          - xe0
+        downlink_{{ vnf_num }}:
+          - xe1
+{% endfor %}
+
+  networks:
+    mgmt:
+      cidr: '10.0.1.0/24'
+{% for vnf_num in range(num_vnfs|int) %}
+    uplink_{{ vnf_num }}:
+      cidr: '10.0.{{ (vnf_num * 2) + 2 }}.0/24'
+      gateway_ip: 'null'
+      port_security_enabled: False
+      enable_dhcp: 'false'
+    downlink_{{ vnf_num }}:
+      cidr: '10.0.{{ (vnf_num * 2) + 3 }}.0/24'
+      gateway_ip: 'null'
+      port_security_enabled: False
+      enable_dhcp: 'false'
+{% endfor %}
index 321b173..4a20fad 100644 (file)
@@ -81,12 +81,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
index 05723ca..a3ac21a 100644 (file)
@@ -81,12 +81,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
index db18949..7d7d2b0 100644 (file)
@@ -85,12 +85,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
index 3462d28..52fe8fc 100644 (file)
@@ -81,14 +81,15 @@ context:
   networks:
     mgmt:
       cidr: '10.0.1.0/24'
-    uplink_0:
-      cidr: '10.0.2.0/24'
+{% for vport in range(1,vports,2|int) %}
+    uplink_{{ loop.index0 }}:
+      cidr: '10.0.{{ vport+1 }}.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-{% for vport in range(vports-1|int) %}
-    downlink_{{ vport }}:
-      cidr: '10.0.{{ vport+3 }}.0/24'
+
+    downlink_{{ loop.index0 }}:
+      cidr: '10.0.{{ vport+2 }}.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
index 736f1c4..c34b4d9 100644 (file)
@@ -84,12 +84,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
index d9cc4bc..24f7ce4 100644 (file)
@@ -82,12 +82,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
index ef28946..6370360 100644 (file)
@@ -79,14 +79,15 @@ context:
   networks:
     mgmt:
       cidr: '10.0.1.0/24'
-    uplink_0:
-      cidr: '10.0.2.0/24'
+{% for vport in range(1,vports,2|int) %}
+    uplink_{{ loop.index0 }}:
+      cidr: '10.0.{{ vport+1 }}.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-{% for vport in range(vports-1|int) %}
-    downlink_{{ vport }}:
-      cidr: '10.0.{{ vport+3 }}.0/24'
+
+    downlink_{{ loop.index0 }}:
+      cidr: '10.0.{{ vport+2 }}.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
index 4e2e70b..29277ca 100644 (file)
@@ -49,7 +49,7 @@ scenarios:
   runner:
     type: Duration
     # we kill after duration, independent of test duration, so set this high
-    duration: 300
+    duration: 1600
 
 context:
   name: yardstick
@@ -89,12 +89,12 @@ context:
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_1:
+    uplink_1:
       cidr: '10.0.4.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
       enable_dhcp: 'false'
-    downlink_2:
+    downlink_1:
       cidr: '10.0.5.0/24'
       gateway_ip: 'null'
       port_security_enabled: False
index 6753645..f7569b3 100644 (file)
 # 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.
-
-access-list1:
-  acl:
-    access-list-entries:
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 152.16.0.0/24
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 0.0.0.0/0
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1588
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 0.0.0.0/0
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 152.16.0.0/24
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1589
-    acl-name: sample-ipv4-acl
-    acl-type: ipv4-acl
+---
+access-list-entries:
+  -
+    actions: [drop,count]
+    matches:
+      destination-ipv4-network: 152.16.0.0/24
+      destination-port-range:
+        lower-port: 0
+        upper-port: 65535
+      source-ipv4-network: 0.0.0.0/0
+      source-port-range:
+        lower-port: 0
+        upper-port: 65535
+    rule-name: rule1588
+  -
+    actions: [drop,count]
+    matches:
+      destination-ipv4-network: 0.0.0.0/0
+      destination-port-range:
+        lower-port: 0
+        upper-port: 65535
+      source-ipv4-network: 152.16.0.0/24
+      source-port-range:
+        lower-port: 0
+        upper-port: 65535
+    rule-name: rule1589
diff --git a/samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_64B_trex_iterationipc.yaml b/samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_64B_trex_iterationipc.yaml
new file mode 100644 (file)
index 0000000..184ed68
--- /dev/null
@@ -0,0 +1,96 @@
+# Copyright (c) 2016-2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+
+---
+{% set provider = provider or none %}
+{% set physical_networks = physical_networks or ['physnet1', 'physnet2'] %}
+{% set segmentation_id = segmentation_id or none %}
+
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf
+  traffic_profile: ../../traffic_profiles/ipv4_throughput.yaml
+  topology: vfw-tg-topology.yaml
+  nodes:
+    tg__0: trafficgen_1.yardstick
+    vnf__0: vnf.yardstick
+  options:
+    hugepages_gb: 8
+    framesize:
+      uplink: {64B: 100}
+      downlink: {64B: 100}
+    flow:
+      src_ip: [{'tg__0': 'xe0'}]
+      dst_ip: [{'tg__0': 'xe1'}]
+      count: 1
+    traffic_type: 4
+    rfc2544:
+      allowed_drop_rate: 0.0001 - 0.0001
+    vnf__0:
+      rules: acl_1rule.yaml
+      vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1}
+  runner:
+    type: IterationIPC
+    iterations: 10
+    timeout: 60
+context:
+  # put node context first, so we don't HEAT deploy if node has errors
+  name: yardstick
+  image: yardstick-samplevnfs
+  flavor:
+    vcpus: 10
+    ram: 12288
+    disk: 6
+    extra_specs:
+      hw:cpu_sockets: 1
+      hw:cpu_cores: 10
+      hw:cpu_threads: 1
+  user: ubuntu
+  placement_groups:
+    pgrp1:
+      policy: "availability"
+  servers:
+    vnf:
+      floating_ip: true
+      placement: "pgrp1"
+    trafficgen_1:
+      floating_ip: true
+      placement: "pgrp1"
+  networks:
+    mgmt:
+      cidr: '10.0.1.0/24'
+    xe0:
+      cidr: '10.0.2.0/24'
+      gateway_ip: 'null'
+      {% if provider %}
+      provider: {{ provider }}
+      physical_network: {{ physical_networks[0] }}
+        {% if segmentation_id %}
+      segmentation_id: {{ segmentation_id }}
+        {% endif %}
+      {% endif %}
+      port_security_enabled: False
+      enable_dhcp: 'false'
+    xe1:
+      cidr: '10.0.3.0/24'
+      gateway_ip: 'null'
+      {% if provider %}
+      provider: {{ provider }}
+      physical_network: {{ physical_networks[1] }}
+        {% if segmentation_id %}
+      segmentation_id: {{ segmentation_id }}
+        {% endif %}
+      {% endif %}
+      port_security_enabled: False
+      enable_dhcp: 'false'
diff --git a/samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_64B_trex_scale_out.yaml b/samples/vnf_samples/nsut/vfw/tc_heat_rfc2544_ipv4_1rule_1flow_64B_trex_scale_out.yaml
new file mode 100644 (file)
index 0000000..f140893
--- /dev/null
@@ -0,0 +1,114 @@
+# Copyright (c) 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.
+{% set num_vnfs = num_vnfs or 1 %}
+{% set availability_zone = availability_zone or {} %}
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf
+  traffic_profile: ../../traffic_profiles/ipv4_throughput_scale_out.yaml
+  topology: vfw_tg_topology_scale_out.yaml
+  extra_args:
+    num_vnfs: {{ num_vnfs }}
+  nodes:
+{% for vnf_num in range(num_vnfs|int) %}
+    tg__{{ vnf_num }}: tg_{{ vnf_num }}.yardstick
+    vnf__{{ vnf_num }}: vnf_{{ vnf_num }}.yardstick
+{% endfor %}
+  options:
+    framesize:
+      uplink: {64B: 100}
+      downlink: {64B: 100}
+    flow:
+      src_ip:
+{% for vnf_num in range(num_vnfs|int) %}
+        - {'tg__{{ vnf_num }}': 'xe0'}
+{% endfor %}
+      dst_ip:
+{% for vnf_num in range(num_vnfs|int) %}
+        - {'tg__{{ vnf_num }}': 'xe1'}
+{% endfor %}
+      count: 1
+    traffic_type: 4
+    rfc2544:
+      allowed_drop_rate: 0.0001 - 0.0001
+{% for vnf_num in range(num_vnfs|int) %}
+    vnf__{{ vnf_num }}:
+      rules: acl_1rule.yaml
+      vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1}
+{% endfor %}
+  runner:
+    type: Iteration
+    iterations: 10
+    interval: 35
+context:
+  # put node context first, so we don't HEAT deploy if node has errors
+  name: yardstick
+  image: yardstick-samplevnfs
+  flavor:
+    vcpus: 10
+    ram: 20480
+    disk: 6
+    extra_specs:
+      hw:cpu_sockets: 1
+      hw:cpu_cores: 10
+      hw:cpu_threads: 1
+  user: ubuntu
+  placement_groups:
+    pgrp1:
+      policy: "availability"
+  servers:
+{% for vnf_num in range(num_vnfs|int) %}
+    vnf_{{ vnf_num }}:
+      floating_ip: true
+      placement: "pgrp1"
+      {% if 'vnf_%s'|format(vnf_num) in availability_zone %}
+      availability_zone: "{{ availability_zone['vnf_%s'|format(vnf_num)] }}"
+      {% endif %}
+      network_ports:
+        mgmt:
+          - mgmt
+        uplink_{{ vnf_num }}:
+          - xe0
+        downlink_{{ vnf_num }}:
+          - xe1
+    tg_{{ vnf_num }}:
+      floating_ip: true
+      placement: "pgrp1"
+      {% if 'tg_%s'|format(vnf_num) in availability_zone %}
+      availability_zone: "{{ availability_zone['tg_%s'|format(vnf_num)] }}"
+      {% endif %}
+      network_ports:
+        mgmt:
+          - mgmt
+        uplink_{{ vnf_num }}:
+          - xe0
+        downlink_{{ vnf_num }}:
+          - xe1
+{% endfor %}
+  networks:
+    mgmt:
+      cidr: '10.0.1.0/24'
+{% for vnf_num in range(num_vnfs|int) %}
+    uplink_{{ vnf_num }}:
+      cidr: '10.0.{{ (vnf_num * 2) + 2 }}.0/24'
+      gateway_ip: 'null'
+      port_security_enabled: False
+      enable_dhcp: 'false'
+    downlink_{{ vnf_num }}:
+      cidr: '10.0.{{ (vnf_num * 2) + 3 }}.0/24'
+      gateway_ip: 'null'
+      port_security_enabled: False
+      enable_dhcp: 'false'
+{% endfor %}
diff --git a/samples/vnf_samples/nsut/vfw/vfw_tg_topology_scale_out.yaml b/samples/vnf_samples/nsut/vfw/vfw_tg_topology_scale_out.yaml
new file mode 100644 (file)
index 0000000..8bd01b7
--- /dev/null
@@ -0,0 +1,53 @@
+# Copyright (c) 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.
+{% set num_vnfs = get(extra_args, 'num_vnfs', 1) %}
+---
+nsd:nsd-catalog:
+    nsd:
+    -   id: 3tg-topology
+        name: 3tg-topology
+        short-name: 3tg-topology
+        description: 3tg-topology
+        constituent-vnfd:
+{% for vnf_num in range(num_vnfs|int) %}
+        -   member-vnf-index: '{{ (vnf_num * 2) + 1 }}'
+            vnfd-id-ref: tg__{{ vnf_num }}
+            VNF model: ../../vnf_descriptors/tg_rfc2544_tpl.yaml
+        -   member-vnf-index: '{{ (vnf_num * 2) + 2 }}'
+            vnfd-id-ref: vnf__{{ vnf_num }}
+            VNF model: ../../vnf_descriptors/vfw_vnf.yaml
+{% endfor %}
+        vld:
+{% for vnf_num in range(num_vnfs|int) %}
+        -   id: uplink_{{ vnf_num }}
+            name: tg__{{ vnf_num }} to vnf__{{ vnf_num }} link {{ (vnf_num * 2) + 1 }}
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '{{ (vnf_num * 2) + 1 }}'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: tg__{{ vnf_num }}
+            -   member-vnf-index-ref: '{{ (vnf_num * 2) + 2 }}'
+                vnfd-connection-point-ref: xe0
+                vnfd-id-ref: vnf__{{ vnf_num }}
+        -   id: downlink_{{ vnf_num }}
+            name: vnf__{{ vnf_num }} to tg__{{ vnf_num }} link {{ (vnf_num * 2) + 2 }}
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '{{ (vnf_num * 2) + 2 }}'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: vnf__{{ vnf_num }}
+            -   member-vnf-index-ref: '{{ (vnf_num * 2) + 1 }}'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: tg__{{ vnf_num }}
+{% endfor %}
index f862abd..98b1bf9 100644 (file)
@@ -43,8 +43,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
   ipv4:
index a321887..ee04153 100644 (file)
@@ -43,8 +43,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
   ipv4:
index d849ed8..19f0836 100644 (file)
@@ -43,8 +43,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
   ipv4:
index c03b28d..95fa0b6 100644 (file)
@@ -43,8 +43,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
   ipv4:
index ad703f2..43f5209 100644 (file)
@@ -44,8 +44,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: IXIARFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 [% for vnf_num in range(num_vnfs|int) %]
 uplink_[[ vnf_num ]]:
index 75927d4..a025a69 100644 (file)
@@ -44,8 +44,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 [% for vnf_num in range(num_vnfs|int) %]
 uplink_[[ vnf_num ]]:
index 5001632..081d630 100644 (file)
@@ -44,8 +44,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: IXIARFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 [% for vnf_num in range(num_vnfs|int) %]
 uplink_[[ vnf_num ]]:
index 78e5f51..d93bf11 100644 (file)
@@ -44,8 +44,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: IXIARFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 [% for vnf_num in range(num_vnfs|int) %]
 uplink_[[ vnf_num ]]:
index 73c4109..0e842d4 100644 (file)
@@ -44,8 +44,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 [% for vnf_num in range(num_vnfs|int) %]
 uplink_[[ vnf_num ]]:
index d2cc18c..b9e0c8c 100644 (file)
@@ -44,7 +44,8 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
+  duration: {{ duration }}
+
 {% set count = 0 %}
 {% for vport in range(vports|int) %}
 uplink_{{vport}}:
index 5b5b447..c267e76 100644 (file)
@@ -42,8 +42,7 @@ description:     Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type : RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate : 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
       ipv4:
index 80d0872..1ff47a5 100644 (file)
@@ -43,8 +43,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
   ipv4:
index d6c9164..2b3e6f3 100644 (file)
@@ -43,8 +43,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
   ipv4:
index 55610b0..7df0682 100644 (file)
@@ -43,8 +43,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
   ipv4:
index d455bcc..82c487e 100644 (file)
@@ -44,8 +44,7 @@ description: Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type: RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate: 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 [% for vnf_num in range(num_vnfs|int) %]
 uplink_[[ vnf_num ]]:
index 61cbd4e..809415a 100644 (file)
@@ -42,8 +42,7 @@ description:     Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type : RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate : 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
       ipv4:
diff --git a/samples/vnf_samples/traffic_profiles/ipv4_throughput_scale_out.yaml b/samples/vnf_samples/traffic_profiles/ipv4_throughput_scale_out.yaml
new file mode 100644 (file)
index 0000000..71e9e81
--- /dev/null
@@ -0,0 +1,102 @@
+# Copyright (c) 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.
+
+# flow definition for ACL tests - 1K flows - ipv4 only
+#
+# the number of flows defines the widest range of parameters
+# for example if srcip_range=1.0.0.1-1.0.0.255 and dst_ip_range=10.0.0.1-10.0.1.255
+# and it should define only 16 flows
+#
+#there is assumption that packets generated will have a random sequences of following addresses pairs
+# in the packets
+# 1. src=1.x.x.x(x.x.x =random from 1..255) dst=10.x.x.x (random from 1..512)
+# 2. src=1.x.x.x(x.x.x =random from 1..255) dst=10.x.x.x (random from 1..512)
+# ...
+# 512. src=1.x.x.x(x.x.x =random from 1..255) dst=10.x.x.x (random from 1..512)
+#
+# not all combination should be filled
+# Any other field with random range will be added to flow definition
+#
+# the example.yaml provides all possibilities for traffic generation
+#
+# the profile defines a public and private side to make limited traffic correlation
+# between private and public side same way as it is made by IXIA solution.
+#
+{% set num_vnfs = get(extra_args, 'num_vnfs', 1) %}
+---
+schema: "nsb:traffic_profile:0.1"
+name:            rfc2544
+description:     Traffic profile to run RFC2544 latency
+traffic_profile:
+  traffic_type : RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
+  frame_rate : 100  # pc of linerate
+  # that specifies a range (e.g. ipv4 address, port)
+{% for vnf_num in range(num_vnfs|int) %}
+uplink_{{ vnf_num }}:
+      ipv4:
+        id: {{ (vnf_num * 2) + 1 }}
+        outer_l2:
+            framesize:
+                64B: "{{get(imix, 'imix.uplink.64B', '0') }}"
+                128B: "{{get(imix, 'imix.uplink.128B', '0') }}"
+                256B: "{{get(imix, 'imix.uplink.256B', '0') }}"
+                373B: "{{get(imix, 'imix.uplink.373B', '0') }}"
+                512B: "{{get(imix, 'imix.uplink.512B', '0') }}"
+                570B: "{{get(imix, 'imix.uplink.570B', '0') }}"
+                1024B: "{{get(imix, 'imix.uplink.1024B', '0') }}"
+                1280B: "{{get(imix, 'imix.uplink.1280B', '0') }}"
+                1400B: "{{get(imix, 'imix.uplink.1400B', '0') }}"
+                1500B: "{{get(imix, 'imix.uplink.1500B', '0') }}"
+                1518B: "{{get(imix, 'imix.uplink.1518B', '0') }}"
+
+        outer_l3v4:
+            proto: "udp"
+            srcip4: "{{get(flow, 'flow.src_ip_{{ vnf_num }}', '10.0.2.1-10.0.2.255') }}"
+            dstip4: "{{get(flow, 'flow.dst_ip_{{ vnf_num }}', '10.0.3.1-10.0.3.255') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
+            ttl: 32
+            dscp: 0
+        outer_l4:
+            srcport: "{{get(flow, 'flow.src_port_{{ vnf_num }}', '1234-4321') }}"
+            dstport: "{{get(flow, 'flow.dst_port_{{ vnf_num }}', '2001-4001') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
+downlink_{{ vnf_num }}:
+      ipv4:
+        id: {{ (vnf_num * 2) + 2 }}
+        outer_l2:
+            framesize:
+                64B: "{{ get(imix, 'imix.downlink.64B', '0') }}"
+                128B: "{{ get(imix, 'imix.downlink.128B', '0') }}"
+                256B: "{{ get(imix, 'imix.downlink.256B', '0') }}"
+                373b: "{{ get(imix, 'imix.downlink.373B', '0') }}"
+                512B: "{{ get(imix, 'imix.downlink.512B', '0') }}"
+                570B: "{{get(imix, 'imix.downlink.570B', '0') }}"
+                1024B: "{{get(imix, 'imix.downlink.1024B', '0') }}"
+                1280B: "{{get(imix, 'imix.downlink.1280B', '0') }}"
+                1400B: "{{get(imix, 'imix.downlink.1400B', '0') }}"
+                1500B: "{{get(imix, 'imix.downlink.1500B', '0') }}"
+                1518B: "{{get(imix, 'imix.downlink.1518B', '0') }}"
+
+        outer_l3v4:
+            proto: "udp"
+            srcip4: "{{get(flow, 'flow.dst_ip_{{ vnf_num }}', '10.0.3.1-10.0.3.255') }}"
+            dstip4: "{{get(flow, 'flow.src_ip_{{ vnf_num }}', '10.0.2.1-10.0.2.255') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
+            ttl: 32
+            dscp: 0
+        outer_l4:
+            srcport: "{{get(flow, 'flow.dst_port_{{ vnf_num }}', '1234-4321') }}"
+            dstport: "{{get(flow, 'flow.src_port_{{ vnf_num }}', '2001-4001') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
+{% endfor %}
index 20bc656..e113c9d 100644 (file)
@@ -42,8 +42,7 @@ description:     Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type : RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate : 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
       ipv4:
index 7b66d66..b346729 100644 (file)
@@ -28,8 +28,7 @@ description:     Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type : IXIARFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate : 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
       ipv4:
index 8fdfe9b..513aefb 100644 (file)
@@ -28,8 +28,7 @@ description:     Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type : IXIARFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate : 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
-
+  duration: {{ duration }}
 
 uplink_0:
       ipv4:
index 4d73b8f..aad7515 100644 (file)
@@ -42,7 +42,7 @@ description:     Traffic profile to run RFC2544 latency
 traffic_profile:
   traffic_type : IXIARFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
   frame_rate : 100  # pc of linerate
-  # that specifies a range (e.g. ipv4 address, port)
+  injection_time: {{ injection_time }}
 
 uplink_0:
       ipv4:
index 59d10f0..6705fb1 100644 (file)
@@ -19,7 +19,7 @@ description:     Prox BNG traffic profile
 
 traffic_profile:
   traffic_type: ProxBinSearchProfile
-  tolerated_loss: 100.0 #0.001
+  tolerated_loss: 5
   test_precision: 0.01
 # The minimum size of the Ethernet frame for the BNG test is 78 bytes.
   packet_sizes: [78]
index 7aab8dd..c9aec0e 100644 (file)
@@ -19,11 +19,11 @@ description:     Prox vPE traffic profile
 
 traffic_profile:
   traffic_type: ProxBinSearchProfile
-  tolerated_loss: 100.0 #0.001
-  test_precision: 0.01
+  tolerated_loss: 0.001 #0.001
+  test_precision: 0.1
 # The minimum size of the Ethernet frame for the vPE test is 68 bytes.
   packet_sizes: [68]
-  duration: 5
+  duration: 60
   lower_bound: 0.0
   upper_bound: 100.0
 
index 4828e98..7825cc5 100644 (file)
@@ -14,8 +14,8 @@ testtools==2.3.0            # OSI Approved  MIT License
 unittest2==1.1.0            # OSI Approved  BSD License
 
 # NOTE(ralonsoh): to be removed, only for coverage support
-python-heatclient==1.8.1        # OSI Approved  Apache Software License
+python-heatclient==1.11.0        # OSI Approved  Apache Software License
 
-# Yardstick F release <-> OpenStack Pike release
-openstack_requirements==1.1.0   # OSI Approved  Apache Software License
--e git+https://github.com/openstack/requirements.git@stable/pike#egg=os_requirements
+# Yardstick G release <-> OpenStack Queens release
+openstack_requirements==1.2.0   # OSI Approved  Apache Software License
+-e git+https://github.com/openstack/requirements.git@stable/queens#egg=os_requirements
index 4faa0bc..8bfe446 100644 (file)
@@ -62,7 +62,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 7f8c229..596db25 100644 (file)
@@ -59,7 +59,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 101c421..756c14d 100644 (file)
@@ -60,7 +60,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index fe244e8..cf12436 100644 (file)
@@ -64,7 +64,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 22e5760..c905302 100644 (file)
@@ -78,13 +78,10 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
       segmentation_id: {{segmentation_id}}
         {% endif %}
       {% endif %}
-    #test-sriov:
-      #cidr: '10.0.1.0/24'
-      #provider: "sriov"
index 3c5f72d..cefa505 100644 (file)
@@ -64,7 +64,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index cf97068..e84e113 100644 (file)
@@ -49,7 +49,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index ee36c6c..9980022 100644 (file)
@@ -61,7 +61,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index b8b208f..a1058bc 100644 (file)
@@ -50,7 +50,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index bd0fe36..78c9e85 100644 (file)
@@ -43,7 +43,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 7136a9e..c2c176b 100644 (file)
@@ -181,7 +181,7 @@ contexts:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 3622b40..a6cf6a2 100644 (file)
@@ -95,7 +95,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 59fb95d..2250ae5 100644 (file)
@@ -95,7 +95,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 2a40823..3bfaff9 100644 (file)
@@ -49,7 +49,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 7ea10d8..8cbd247 100644 (file)
@@ -97,7 +97,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index b6a944b..c1ce2c5 100644 (file)
@@ -95,7 +95,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 09930d4..d237fa9 100644 (file)
@@ -97,7 +97,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 8c0edac..c5e799c 100644 (file)
@@ -58,7 +58,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 9c15acc..04a9225 100644 (file)
@@ -45,7 +45,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 4b67f0f..85b6c91 100644 (file)
@@ -55,7 +55,7 @@ context:
   networks:
     test:
       cidr: "10.0.1.0/24"
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 6315fdc..158f064 100755 (executable)
@@ -81,7 +81,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
index 472aabe..9df1657 100644 (file)
@@ -58,7 +58,7 @@ context:
   networks:
     test:
       cidr: '10.0.1.0/24'
-      {% if provider == "vlan" %}
+      {% if provider == "vlan" or provider == "sriov" %}
       provider: {{provider}}
       physical_network: {{physical_network}}
         {% if segmentation_id %}
diff --git a/tests/opnfv/test_suites/opnfv_os-odl-ovs-noha_daily.yaml b/tests/opnfv/test_suites/opnfv_os-odl-ovs-noha_daily.yaml
new file mode 100644 (file)
index 0000000..83b3700
--- /dev/null
@@ -0,0 +1,64 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+---
+# os-odl-ovs-noha daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "os-odl-ovs-noha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+  file_name: opnfv_yardstick_tc002.yaml
+-
+  file_name: opnfv_yardstick_tc005.yaml
+-
+  file_name: opnfv_yardstick_tc010.yaml
+-
+  file_name: opnfv_yardstick_tc011.yaml
+  constraint:
+      installer: compass,fuel
+-
+  file_name: opnfv_yardstick_tc012.yaml
+-
+  file_name: opnfv_yardstick_tc014.yaml
+-
+  file_name: opnfv_yardstick_tc037.yaml
+-
+  file_name: opnfv_yardstick_tc055.yaml
+  constraint:
+      installer: compass
+      pod: huawei-pod1
+  task_args:
+      huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml",
+      "host": "node5"}'
+-
+  file_name: opnfv_yardstick_tc063.yaml
+  constraint:
+      installer: compass
+      pod: huawei-pod1
+  task_args:
+      huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml",
+      "host": "node5"}'
+-
+  file_name: opnfv_yardstick_tc069.yaml
+-
+  file_name: opnfv_yardstick_tc070.yaml
+-
+  file_name: opnfv_yardstick_tc071.yaml
+-
+  file_name: opnfv_yardstick_tc072.yaml
+-
+  file_name: opnfv_yardstick_tc075.yaml
+  constraint:
+      installer: compass
+      pod: huawei-pod1
+  task_args:
+      huawei-pod1: '{"file": "etc/yardstick/nodes/compass_sclab_physical/pod.yaml",
+      "host": "node1"}'
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
deleted file mode 100644 (file)
index 95b2b8a..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2017 Intel Corporation\r
-#\r
-# Licensed under the Apache License, Version 2.0 (the "License");\r
-# you may not use this file except in compliance with the License.\r
-# You may obtain a copy of the License at\r
-#\r
-#      http://www.apache.org/licenses/LICENSE-2.0\r
-#\r
-# Unless required by applicable law or agreed to in writing, software\r
-# distributed under the License is distributed on an "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-# See the License for the specific language governing permissions and\r
-# limitations under the License.\r
-\r
-import sys\r
-\r
-import mock\r
-\r
-from yardstick import tests\r
-\r
-# NOTE(ralonsoh): to be removed. Replace all occurrences of\r
-# tests.unit.STL_MOCKS with yardstick.tests.STL_MOCKS\r
-STL_MOCKS = tests.STL_MOCKS\r
-\r
-mock_stl = mock.patch.dict(sys.modules, tests.STL_MOCKS)\r
-mock_stl.start()\r
diff --git a/tests/unit/network_services/__init__.py b/tests/unit/network_services/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
index c6e928d..4e54a64 100644 (file)
@@ -44,14 +44,12 @@ run_coverage_test() {
     baseline_report=$(mktemp -t yardstick_coverageXXXXXXX)
 
     find . -type f -name "*.pyc" -delete
+    coverage erase
 
-    # Temporarily run tests from two directories, until all tests have moved
-    coverage run -p -m unittest discover ./tests/unit
     coverage run -p -m unittest discover ./yardstick/tests/unit
     coverage combine
 
-    # Temporarily omit yardstick/tests from the report
-    coverage report --omit=yardstick/tests/*/* > ${baseline_report}
+    coverage report > ${baseline_report}
     coverage erase
 
     # debug awk
@@ -72,13 +70,10 @@ run_coverage_test() {
 
     find . -type f -name "*.pyc" -delete
 
-    # Temporarily run tests from two directories, until all tests have moved
-    coverage run -p -m unittest discover ./tests/unit
     coverage run -p -m unittest discover ./yardstick/tests/unit
     coverage combine
 
-    # Temporarily omit yardstick/tests from the report
-    coverage report --omit=yardstick/tests/*/* > ${current_report}
+    coverage report > ${current_report}
     coverage erase
 
     rm -rf cover-$PY_VER
index 32c4f19..49f628e 100755 (executable)
@@ -28,17 +28,8 @@ run_tests() {
 
     echo "Running unittest ... "
     if [ $FILE_OPTION == "f" ]; then
-        python -m unittest discover -v -s tests/unit > $logfile 2>&1
-        if [ $? -ne 0 ]; then
-            echo "FAILED, results in $logfile"
-            exit 1
-        fi
-        python -m unittest discover -v -s yardstick/tests/unit >> $logfile 2>&1
+        python -m unittest discover -v -s yardstick/tests/unit > $logfile 2>&1
     else
-        python -m unittest discover -v -s tests/unit
-        if [ $? -ne 0 ]; then
-            exit 1
-        fi
         python -m unittest discover -v -s yardstick/tests/unit
     fi
 
index 692c168..f3f5879 100644 (file)
@@ -8,10 +8,14 @@
 ##############################################################################
 
 import abc
+import errno
 import six
+import os
 
 from yardstick.common import constants
 from yardstick.common import utils
+from yardstick.common import yaml_loader
+from yardstick.common.constants import YARDSTICK_ROOT_PATH
 
 
 class Flags(object):
@@ -45,20 +49,13 @@ class Context(object):
     list = []
     SHORT_TASK_ID_LEN = 8
 
-    @staticmethod
-    def split_name(name, sep='.'):
-        try:
-            name_iter = iter(name.split(sep))
-        except AttributeError:
-            # name is not a string
-            return None, None
-        return next(name_iter), next(name_iter, None)
-
-    def __init__(self):
+    def __init__(self, host_name_separator='.'):
         Context.list.append(self)
         self._flags = Flags()
         self._name = None
         self._task_id = None
+        self.file_path = None
+        self._host_name_separator = host_name_separator
 
     def init(self, attrs):
         """Initiate context"""
@@ -68,6 +65,35 @@ class Context(object):
         self._name_task_id = '{}-{}'.format(
             self._name, self._task_id[:self.SHORT_TASK_ID_LEN])
 
+    def split_host_name(self, name):
+        if (isinstance(name, six.string_types)
+                and self._host_name_separator in name):
+            return tuple(name.split(self._host_name_separator, 1))
+        return None, None
+
+    def read_pod_file(self, attrs):
+        self.file_path = file_path = attrs.get("file", "pod.yaml")
+        try:
+            cfg = yaml_loader.read_yaml_file(self.file_path)
+        except IOError as io_error:
+            if io_error.errno != errno.ENOENT:
+                raise
+
+            self.file_path = os.path.join(YARDSTICK_ROOT_PATH, file_path)
+            cfg = yaml_loader.read_yaml_file(self.file_path)
+
+        for node in cfg["nodes"]:
+            node["ctx_type"] = self.__context_type__
+
+        self.nodes.extend(cfg["nodes"])
+        self.controllers.extend([node for node in cfg["nodes"]
+                                 if node.get("role") == "Controller"])
+        self.computes.extend([node for node in cfg["nodes"]
+                              if node.get("role") == "Compute"])
+        self.baremetals.extend([node for node in cfg["nodes"]
+                                if node.get("role") == "Baremetal"])
+        return cfg
+
     @property
     def name(self):
         if self._flags.no_setup or self._flags.no_teardown:
@@ -79,6 +105,10 @@ class Context(object):
     def assigned_name(self):
         return self._name
 
+    @property
+    def host_name_separator(self):
+        return self._host_name_separator
+
     @staticmethod
     def get_cls(context_type):
         """Return class of specified type."""
@@ -128,6 +158,25 @@ class Context(object):
             raise ValueError("context not found for server %r" %
                              attr_name)
 
+    @staticmethod
+    def get_physical_nodes():
+        """return physical node names for all contexts"""
+        physical_nodes = {}
+        for context in Context.list:
+            nodes = context._get_physical_nodes()
+            physical_nodes.update({context._name: nodes})
+
+        return physical_nodes
+
+    @staticmethod
+    def get_physical_node_from_server(server_name):
+        """return physical nodes for all contexts"""
+        context = Context.get_context_from_server(server_name)
+        if context == None:
+            return  None
+
+        return context._get_physical_node_for_server(server_name)
+
     @staticmethod
     def get_context_from_server(attr_name):
         """lookup context info by name from node config
@@ -157,3 +206,15 @@ class Context(object):
         except StopIteration:
             raise ValueError("context not found for server %r" %
                              attr_name)
+
+    @abc.abstractmethod
+    def _get_physical_nodes(self):
+        """return the list of physical nodes in context"""
+
+    @abc.abstractmethod
+    def _get_physical_node_for_server(self, server_name):
+        """ Find physical node for given server
+
+        :param server_name: (string) Server name in scenario
+        :return string:  <node_name>.<context_name>
+        """
index a9e4564..36e8854 100644 (file)
@@ -32,3 +32,9 @@ class DummyContext(Context):
 
     def _get_network(self, attr_name):
         return None
+
+    def _get_physical_nodes(self):
+        return None
+
+    def _get_physical_node_for_server(self, server_name):
+        return None
index 8286182..ac85b6f 100644 (file)
@@ -29,6 +29,7 @@ from yardstick.common import constants as consts
 from yardstick.common import utils
 from yardstick.common.utils import source_env
 from yardstick.ssh import SSH
+from yardstick.common import openstack_utils
 
 LOG = logging.getLogger(__name__)
 
@@ -68,6 +69,12 @@ class HeatContext(Context):
         self.shade_client = None
         self.heat_timeout = None
         self.key_filename = None
+        self.shade_client = None
+        self.operator_client = None
+        self.nodes = []
+        self.controllers = []
+        self.computes = []
+        self.baremetals = []
         super(HeatContext, self).__init__()
 
     @staticmethod
@@ -96,6 +103,14 @@ class HeatContext(Context):
 
         self.template_file = attrs.get("heat_template")
 
+        self.shade_client = openstack_utils.get_shade_client()
+        self.operator_client = openstack_utils.get_shade_operator_client()
+
+        try:
+            self.read_pod_file(attrs)
+        except IOError:
+            LOG.warning("No pod file specified. NVFi metrics will be disabled")
+
         self.heat_timeout = attrs.get("timeout", DEFAULT_HEAT_TIMEOUT)
         if self.template_file:
             self.heat_parameters = attrs.get("heat_parameters")
@@ -465,7 +480,7 @@ class HeatContext(Context):
         with attribute name mapping when using external heat templates
         """
         if isinstance(attr_name, collections.Mapping):
-            node_name, cname = self.split_name(attr_name['name'])
+            node_name, cname = self.split_host_name(attr_name['name'])
             if cname is None or cname != self.name:
                 return None
 
@@ -528,3 +543,30 @@ class HeatContext(Context):
             "physical_network": network.physical_network,
         }
         return result
+
+    def _get_physical_nodes(self):
+        return self.nodes
+
+    def _get_physical_node_for_server(self, server_name):
+        node_name, ctx_name = self.split_host_name(server_name)
+        if ctx_name is None or self.name != ctx_name:
+            return None
+
+        matching_nodes = [s for s in self.servers if s.name == node_name]
+        if len(matching_nodes) == 0:
+            return None
+
+        server = openstack_utils.get_server(self.shade_client,
+                                            name_or_id=server_name)
+
+        if server:
+            server = server.toDict()
+            list_hypervisors = self.operator_client.list_hypervisors()
+
+            for hypervisor in list_hypervisors:
+                if hypervisor.hypervisor_hostname == server['OS-EXT-SRV-ATTR:hypervisor_hostname']:
+                    for node in self.nodes:
+                        if node['ip'] == hypervisor.host_ip:
+                            return "{}.{}".format(node['name'], self._name)
+
+        return None
index ddfc530..4ba9eee 100644 (file)
@@ -33,8 +33,7 @@ class KubernetesContext(Context):
         self.key_path = ''
         self.public_key_path = ''
         self.template = None
-
-        super(KubernetesContext, self).__init__()
+        super(KubernetesContext, self).__init__(host_name_separator='-')
 
     def init(self, attrs):
         super(KubernetesContext, self).init(attrs)
@@ -175,3 +174,9 @@ class KubernetesContext(Context):
 
     def _get_network(self, attr_name):
         return None
+
+    def _get_physical_nodes(self):
+        return None
+
+    def _get_physical_node_for_server(self, server_name):
+        return None
index fa619a9..d3af989 100644 (file)
@@ -8,7 +8,6 @@
 ##############################################################################
 
 from __future__ import absolute_import
-import errno
 import subprocess
 import os
 import collections
@@ -22,7 +21,7 @@ from yardstick import ssh
 from yardstick.benchmark.contexts.base import Context
 from yardstick.common.constants import ANSIBLE_DIR, YARDSTICK_ROOT_PATH
 from yardstick.common.ansible_common import AnsibleCommon
-from yardstick.common.yaml_loader import yaml_load
+from yardstick.common.exceptions import ContextUpdateCollectdForNodeError
 
 LOG = logging.getLogger(__name__)
 
@@ -49,40 +48,11 @@ class NodeContext(Context):
         }
         super(NodeContext, self).__init__()
 
-    def read_config_file(self):
-        """Read from config file"""
-
-        with open(self.file_path) as stream:
-            LOG.info("Parsing pod file: %s", self.file_path)
-            cfg = yaml_load(stream)
-        return cfg
-
     def init(self, attrs):
         """initializes itself from the supplied arguments"""
         super(NodeContext, self).init(attrs)
 
-        self.file_path = file_path = attrs.get("file", "pod.yaml")
-
-        try:
-            cfg = self.read_config_file()
-        except IOError as io_error:
-            if io_error.errno != errno.ENOENT:
-                raise
-
-            self.file_path = os.path.join(YARDSTICK_ROOT_PATH, file_path)
-            cfg = self.read_config_file()
-
-        self.nodes.extend(cfg["nodes"])
-        self.controllers.extend([node for node in cfg["nodes"]
-                                 if node.get("role") == "Controller"])
-        self.computes.extend([node for node in cfg["nodes"]
-                              if node.get("role") == "Compute"])
-        self.baremetals.extend([node for node in cfg["nodes"]
-                                if node.get("role") == "Baremetal"])
-        LOG.debug("Nodes: %r", self.nodes)
-        LOG.debug("Controllers: %r", self.controllers)
-        LOG.debug("Computes: %r", self.computes)
-        LOG.debug("BareMetals: %r", self.baremetals)
+        cfg = self.read_pod_file(attrs)
 
         self.env = attrs.get('env', {})
         self.attrs = attrs
@@ -135,11 +105,37 @@ class NodeContext(Context):
             playbook = os.path.join(ANSIBLE_DIR, playbook)
         return playbook
 
+    def _get_physical_nodes(self):
+        return self.nodes
+
+    def _get_physical_node_for_server(self, server_name):
+
+        node_name, context_name = self.split_host_name(server_name)
+
+        if context_name is None or self.name != context_name:
+            return None
+
+        for n in (n for n in self.nodes if n["name"] == node_name):
+            return "{}.{}".format(n["name"], self._name)
+
+        return None
+
+    def update_collectd_options_for_node(self, options, attr_name):
+        node_name, _ = self.split_host_name(attr_name)
+
+        matching_nodes = (n for n in self.nodes if n["name"] == node_name)
+        try:
+            node = next(matching_nodes)
+        except StopIteration:
+            raise ContextUpdateCollectdForNodeError(attr_name=attr_name)
+
+        node["collectd"] = options
+
     def _get_server(self, attr_name):
         """lookup server info by name from context
         attr_name: a name for a server listed in nodes config file
         """
-        node_name, name = self.split_name(attr_name)
+        node_name, name = self.split_host_name(attr_name)
         if name is None or self.name != name:
             return None
 
index 320c61c..ecddcbb 100644 (file)
@@ -26,7 +26,7 @@ import xml.etree.ElementTree as ET
 from yardstick import ssh
 from yardstick.common import constants
 from yardstick.common import exceptions
-from yardstick.common.yaml_loader import yaml_load
+from yardstick.common import yaml_loader
 from yardstick.network_services.utils import PciAddress
 from yardstick.network_services.helpers.cpu import CpuSysCores
 
@@ -394,26 +394,18 @@ class StandaloneContextHelper(object):
 
         return pf_vfs
 
-    def read_config_file(self):
-        """Read from config file"""
-
-        with open(self.file_path) as stream:
-            LOG.info("Parsing pod file: %s", self.file_path)
-            cfg = yaml_load(stream)
-        return cfg
-
     def parse_pod_file(self, file_path, nfvi_role='Sriov'):
         self.file_path = file_path
         nodes = []
         nfvi_host = []
         try:
-            cfg = self.read_config_file()
+            cfg = yaml_loader.read_yaml_file(self.file_path)
         except IOError as io_error:
             if io_error.errno != errno.ENOENT:
                 raise
             self.file_path = os.path.join(constants.YARDSTICK_ROOT_PATH,
                                           file_path)
-            cfg = self.read_config_file()
+            cfg = yaml_loader.read_yaml_file(self.file_path)
 
         nodes.extend([node for node in cfg["nodes"] if str(node["role"]) != nfvi_role])
         nfvi_host.extend([node for node in cfg["nodes"] if str(node["role"]) == nfvi_role])
index b9e66a4..e6a6f99 100644 (file)
@@ -298,13 +298,28 @@ class OvsDpdkContext(Context):
         for vm in self.vm_names:
             model.Libvirt.check_if_vm_exists_and_delete(vm, self.connection)
 
+    def _get_physical_nodes(self):
+        return self.nfvi_host
+
+    def _get_physical_node_for_server(self, server_name):
+        node_name, ctx_name = self.split_host_name(server_name)
+        if ctx_name is None or self.name != ctx_name:
+            return None
+
+        matching_nodes = [s for s in self.servers if s == node_name]
+        if len(matching_nodes) == 0:
+            return None
+
+        # self.nfvi_host always contain only one host
+        return "{}.{}".format(self.nfvi_host[0]["name"], self._name)
+
     def _get_server(self, attr_name):
         """lookup server info by name from context
 
         Keyword arguments:
         attr_name -- A name for a server listed in nodes config file
         """
-        node_name, name = self.split_name(attr_name)
+        node_name, name = self.split_host_name(attr_name)
         if name is None or self.name != name:
             return None
 
index 2f93e53..05fac02 100644 (file)
@@ -106,13 +106,29 @@ class SriovContext(Context):
             build_vfs = "echo 0 > /sys/bus/pci/devices/{0}/sriov_numvfs"
             self.connection.execute(build_vfs.format(ports.get('phy_port')))
 
+    def _get_physical_nodes(self):
+        return self.nfvi_host
+
+    def _get_physical_node_for_server(self, server_name):
+
+        # self.nfvi_host always contain only one host.
+        node_name, ctx_name = self.split_host_name(server_name)
+        if ctx_name is None or self.name != ctx_name:
+            return None
+
+        matching_nodes = [s for s in self.servers if s == node_name]
+        if len(matching_nodes) == 0:
+            return None
+
+        return "{}.{}".format(self.nfvi_host[0]["name"], self._name)
+
     def _get_server(self, attr_name):
         """lookup server info by name from context
 
         Keyword arguments:
         attr_name -- A name for a server listed in nodes config file
         """
-        node_name, name = self.split_name(attr_name)
+        node_name, name = self.split_host_name(attr_name)
         if name is None or self.name != name:
             return None
 
index 697cc00..f050e8d 100644 (file)
@@ -619,27 +619,22 @@ class TaskParser(object):       # pragma: no cover
           nodes:
             tg__0: tg_0.yardstick
             vnf__0: vnf_0.yardstick
+
+        NOTE: in Kubernetes context, the separator character between the server
+        name and the context name is "-":
+        scenario:
+          host: host-k8s
+          target: target-k8s
         """
         def qualified_name(name):
-            try:
-                # for openstack
-                node_name, context_name = name.split('.')
-                sep = '.'
-            except ValueError:
-                # for kubernetes, some kubernetes resources don't support
-                # name format like 'xxx.xxx', so we use '-' instead
-                # need unified later
-                node_name, context_name = name.split('-')
-                sep = '-'
-
-            try:
-                ctx = next((context for context in contexts
-                            if context.assigned_name == context_name))
-            except StopIteration:
-                raise y_exc.ScenarioConfigContextNameNotFound(
-                    context_name=context_name)
-
-            return '{}{}{}'.format(node_name, sep, ctx.name)
+            for context in contexts:
+                host_name, ctx_name = context.split_host_name(name)
+                if context.assigned_name == ctx_name:
+                    return '{}{}{}'.format(host_name,
+                                           context.host_name_separator,
+                                           context.name)
+
+            raise y_exc.ScenarioConfigContextNameNotFound(host_name=name)
 
         if 'host' in scenario:
             scenario['host'] = qualified_name(scenario['host'])
index 6aaaed8..ecb59f9 100755 (executable)
@@ -37,6 +37,7 @@ import six
 from six.moves import range
 
 from yardstick.benchmark.runners import base
+from yardstick.common import exceptions as y_exc
 
 LOG = logging.getLogger(__name__)
 
@@ -86,7 +87,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
         loop_iter = six.moves.zip(*param_iters)
     else:
         LOG.warning("iter_type unrecognized: %s", iter_type)
-        raise TypeError("iter_type unrecognized: %s", iter_type)
+        raise TypeError("iter_type unrecognized: %s" % iter_type)
 
     # Populate options and run the requested method for each value combination
     for comb_values in loop_iter:
@@ -105,14 +106,14 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
 
         try:
             result = method(data)
-        except AssertionError as assertion:
+        except y_exc.SLAValidationError as error:
             # SLA validation failed in scenario, determine what to do now
             if sla_action == "assert":
                 raise
             elif sla_action == "monitor":
-                LOG.warning("SLA validation failed: %s", assertion.args)
-                errors = assertion.args
-        except Exception as e:
+                LOG.warning("SLA validation failed: %s", error.args)
+                errors = error.args
+        except Exception as e:  # pylint: disable=broad-except
             errors = traceback.format_exc()
             LOG.exception(e)
         else:
index fbdf6c2..af25574 100755 (executable)
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+#
+# This is a modified copy of ``rally/rally/benchmark/runners/base.py``
 
-# yardstick comment: this is a modified copy of
-# rally/rally/benchmark/runners/base.py
-
-from __future__ import absolute_import
-
+import importlib
 import logging
 import multiprocessing
 import subprocess
 import time
 import traceback
-from subprocess import CalledProcessError
-
-import importlib
 
-from six.moves.queue import Empty
+from six import moves
 
-import yardstick.common.utils as utils
 from yardstick.benchmark.scenarios import base as base_scenario
+from yardstick.common import messaging
+from yardstick.common.messaging import payloads
+from yardstick.common.messaging import producer
+from yardstick.common import utils
 from yardstick.dispatcher.base import Base as DispatcherBase
 
+
 log = logging.getLogger(__name__)
 
 
@@ -41,7 +40,7 @@ def _execute_shell_command(command):
     exitcode = 0
     try:
         output = subprocess.check_output(command, shell=True)
-    except CalledProcessError:
+    except subprocess.CalledProcessError:
         exitcode = -1
         output = traceback.format_exc()
         log.error("exec command '%s' error:\n ", command)
@@ -245,7 +244,7 @@ class Runner(object):
             log.debug("output_queue size %s", self.output_queue.qsize())
             try:
                 result.update(self.output_queue.get(True, 1))
-            except Empty:
+            except moves.queue.Empty:
                 pass
         return result
 
@@ -259,7 +258,7 @@ class Runner(object):
             log.debug("result_queue size %s", self.result_queue.qsize())
             try:
                 one_record = self.result_queue.get(True, 1)
-            except Empty:
+            except moves.queue.Empty:
                 pass
             else:
                 if output_in_influxdb:
@@ -272,3 +271,22 @@ class Runner(object):
         dispatchers = DispatcherBase.get(self.config['output_config'])
         dispatcher = next((d for d in dispatchers if d.__dispatcher_type__ == 'Influxdb'))
         dispatcher.upload_one_record(record, self.case_name, '', task_id=self.task_id)
+
+
+class RunnerProducer(producer.MessagingProducer):
+    """Class implementing the message producer for runners"""
+
+    def __init__(self, _id):
+        super(RunnerProducer, self).__init__(messaging.TOPIC_RUNNER, _id=_id)
+
+    def start_iteration(self, version=1, data=None):
+        data = {} if not data else data
+        self.send_message(
+            messaging.RUNNER_METHOD_START_ITERATION,
+            payloads.RunnerPayload(version=version, data=data))
+
+    def stop_iteration(self, version=1, data=None):
+        data = {} if not data else data
+        self.send_message(
+            messaging.RUNNER_METHOD_STOP_ITERATION,
+            payloads.RunnerPayload(version=version, data=data))
index 60b0348..14fd8bb 100644 (file)
@@ -27,6 +27,7 @@ import traceback
 import time
 
 from yardstick.benchmark.runners import base
+from yardstick.common import exceptions as y_exc
 
 LOG = logging.getLogger(__name__)
 
@@ -70,13 +71,14 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
 
         try:
             result = method(data)
-        except AssertionError as assertion:
+        except y_exc.SLAValidationError as error:
             # SLA validation failed in scenario, determine what to do now
             if sla_action == "assert":
+                benchmark.teardown()
                 raise
             elif sla_action == "monitor":
-                LOG.warning("SLA validation failed: %s", assertion.args)
-                errors = assertion.args
+                LOG.warning("SLA validation failed: %s", error.args)
+                errors = error.args
         # catch all exceptions because with multiprocessing we can have un-picklable exception
         # problems  https://bugs.python.org/issue9400
         except Exception:  # pylint: disable=broad-except
index 63bfc82..88d3c57 100755 (executable)
@@ -27,6 +27,7 @@ import traceback
 import os
 
 from yardstick.benchmark.runners import base
+from yardstick.common import exceptions as y_exc
 
 LOG = logging.getLogger(__name__)
 
@@ -80,10 +81,10 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
 
                 try:
                     method(data)
-                except AssertionError as assertion:
-                    LOG.warning("SLA validation failed: %s" % assertion.args)
+                except y_exc.SLAValidationError as error:
+                    LOG.warning("SLA validation failed: %s", error.args)
                     too_high = True
-                except Exception as e:
+                except Exception as e:  # pylint: disable=broad-except
                     errors = traceback.format_exc()
                     LOG.exception(e)
 
index 20d6da0..4c88f36 100644 (file)
@@ -29,6 +29,7 @@ import traceback
 import os
 
 from yardstick.benchmark.runners import base
+from yardstick.common import exceptions as y_exc
 
 LOG = logging.getLogger(__name__)
 
@@ -75,13 +76,13 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
 
             try:
                 result = method(data)
-            except AssertionError as assertion:
+            except y_exc.SLAValidationError as error:
                 # SLA validation failed in scenario, determine what to do now
                 if sla_action == "assert":
                     raise
                 elif sla_action == "monitor":
-                    LOG.warning("SLA validation failed: %s", assertion.args)
-                    errors = assertion.args
+                    LOG.warning("SLA validation failed: %s", error.args)
+                    errors = error.args
                 elif sla_action == "rate-control":
                     try:
                         scenario_cfg['options']['rate']
diff --git a/yardstick/benchmark/runners/iteration_ipc.py b/yardstick/benchmark/runners/iteration_ipc.py
new file mode 100644 (file)
index 0000000..a0335fd
--- /dev/null
@@ -0,0 +1,205 @@
+# Copyright 2018: Intel Corporation
+# All Rights Reserved.
+#
+#    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.
+
+"""A runner that runs a configurable number of times before it returns. Each
+   iteration has a configurable timeout. The loop control depends on the
+   feedback received from the running VNFs. The context PIDs from the VNFs
+   to listen the messages from are given in the scenario "setup" method.
+"""
+
+import logging
+import multiprocessing
+import time
+import traceback
+
+import os
+
+from yardstick.benchmark.runners import base as base_runner
+from yardstick.common import exceptions
+from yardstick.common import messaging
+from yardstick.common import utils
+from yardstick.common.messaging import consumer
+from yardstick.common.messaging import payloads
+
+
+LOG = logging.getLogger(__name__)
+
+QUEUE_PUT_TIMEOUT = 10
+ITERATION_TIMEOUT = 180
+
+
+class RunnerIterationIPCEndpoint(consumer.NotificationHandler):
+    """Endpoint class for ``RunnerIterationIPCConsumer``"""
+
+    def tg_method_started(self, ctxt, **kwargs):
+        if ctxt['id'] in self._ctx_ids:
+            self._queue.put(
+                {'id': ctxt['id'],
+                 'action': messaging.TG_METHOD_STARTED,
+                 'payload': payloads.TrafficGeneratorPayload.dict_to_obj(
+                     kwargs)},
+                QUEUE_PUT_TIMEOUT)
+
+    def tg_method_finished(self, ctxt, **kwargs):
+        if ctxt['id'] in self._ctx_ids:
+            self._queue.put(
+                {'id': ctxt['id'],
+                 'action': messaging.TG_METHOD_FINISHED,
+                 'payload': payloads.TrafficGeneratorPayload.dict_to_obj(
+                     kwargs)})
+
+    def tg_method_iteration(self, ctxt, **kwargs):
+        if ctxt['id'] in self._ctx_ids:
+            self._queue.put(
+                {'id': ctxt['id'],
+                 'action': messaging.TG_METHOD_ITERATION,
+                 'payload': payloads.TrafficGeneratorPayload.dict_to_obj(
+                     kwargs)})
+
+
+class RunnerIterationIPCConsumer(consumer.MessagingConsumer):
+    """MQ consumer for "IterationIPC" runner"""
+
+    def __init__(self, _id, ctx_ids):
+        self._id = _id
+        self._queue = multiprocessing.Queue()
+        endpoints = [RunnerIterationIPCEndpoint(_id, ctx_ids, self._queue)]
+        super(RunnerIterationIPCConsumer, self).__init__(
+            messaging.TOPIC_TG, ctx_ids, endpoints)
+        self._kpi_per_id = {ctx: [] for ctx in ctx_ids}
+        self.iteration_index = None
+
+    def is_all_kpis_received_in_iteration(self):
+        """Check if all producers registered have sent the ITERATION msg
+
+        During the present iteration, all producers (traffic generators) must
+        start and finish the traffic injection, and at the end of the traffic
+        injection a TG_METHOD_ITERATION must be sent. This function will check
+        all KPIs in the present iteration are received. E.g.:
+          self.iteration_index = 2
+
+          self._kpi_per_id = {
+            'ctx1': [kpi0, kpi1, kpi2],
+            'ctx2': [kpi0, kpi1]}          --> return False
+
+          self._kpi_per_id = {
+            'ctx1': [kpi0, kpi1, kpi2],
+            'ctx2': [kpi0, kpi1, kpi2]}    --> return True
+        """
+        while not self._queue.empty():
+            msg = self._queue.get(True, 1)
+            if msg['action'] == messaging.TG_METHOD_ITERATION:
+                id_iter_list = self._kpi_per_id[msg['id']]
+                id_iter_list.append(msg['payload'].kpi)
+
+        return all(len(id_iter_list) == self.iteration_index
+                   for id_iter_list in self._kpi_per_id.values())
+
+
+def _worker_process(queue, cls, method_name, scenario_cfg,
+                    context_cfg, aborted, output_queue):  # pragma: no cover
+    runner_cfg = scenario_cfg['runner']
+
+    timeout = runner_cfg.get('timeout', ITERATION_TIMEOUT)
+    iterations = runner_cfg.get('iterations', 1)
+    run_step = runner_cfg.get('run_step', 'setup,run,teardown')
+    LOG.info('Worker START. Iterations %d times, class %s', iterations, cls)
+
+    runner_cfg['runner_id'] = os.getpid()
+
+    benchmark = cls(scenario_cfg, context_cfg)
+    method = getattr(benchmark, method_name)
+
+    if 'setup' not in run_step:
+        raise exceptions.RunnerIterationIPCSetupActionNeeded()
+    benchmark.setup()
+    producer_ctxs = benchmark.get_mq_ids()
+    if not producer_ctxs:
+        raise exceptions.RunnerIterationIPCNoCtxs()
+
+    mq_consumer = RunnerIterationIPCConsumer(os.getpid(), producer_ctxs)
+    mq_consumer.start_rpc_server()
+    mq_producer = base_runner.RunnerProducer(scenario_cfg['task_id'])
+
+    iteration_index = 1
+    while 'run' in run_step:
+        LOG.debug('runner=%(runner)s seq=%(sequence)s START',
+                  {'runner': runner_cfg['runner_id'],
+                   'sequence': iteration_index})
+        data = {}
+        result = None
+        errors = ''
+        mq_consumer.iteration_index = iteration_index
+        mq_producer.start_iteration()
+
+        try:
+            utils.wait_until_true(
+                mq_consumer.is_all_kpis_received_in_iteration,
+                timeout=timeout, sleep=2)
+            result = method(data)
+        except Exception:  # pylint: disable=broad-except
+            errors = traceback.format_exc()
+            LOG.exception(errors)
+
+        mq_producer.stop_iteration()
+
+        if result:
+            output_queue.put(result, True, QUEUE_PUT_TIMEOUT)
+        benchmark_output = {'timestamp': time.time(),
+                            'sequence': iteration_index,
+                            'data': data,
+                            'errors': errors}
+        queue.put(benchmark_output, True, QUEUE_PUT_TIMEOUT)
+
+        LOG.debug('runner=%(runner)s seq=%(sequence)s END',
+                  {'runner': runner_cfg['runner_id'],
+                   'sequence': iteration_index})
+
+        iteration_index += 1
+        if iteration_index > iterations or aborted.is_set():
+            LOG.info('"IterationIPC" worker END')
+            break
+
+    if 'teardown' in run_step:
+        try:
+            benchmark.teardown()
+        except Exception:
+            LOG.exception('Exception during teardown process')
+            mq_consumer.stop_rpc_server()
+            raise SystemExit(1)
+
+    LOG.debug('Data queue size = %s', queue.qsize())
+    LOG.debug('Output queue size = %s', output_queue.qsize())
+    mq_consumer.stop_rpc_server()
+
+
+class IterationIPCRunner(base_runner.Runner):
+    """Run a scenario for a configurable number of times.
+
+    Each iteration has a configurable timeout. The loop control depends on the
+    feedback received from the running VNFs. The context PIDs from the VNFs to
+    listen the messages from are given in the scenario "setup" method.
+    """
+    __execution_type__ = 'IterationIPC'
+
+    def _run_benchmark(self, cls, method, scenario_cfg, context_cfg):
+        name = '{}-{}-{}'.format(
+            self.__execution_type__, scenario_cfg.get('type'), os.getpid())
+        self.process = multiprocessing.Process(
+            name=name,
+            target=_worker_process,
+            args=(self.result_queue, cls, method, scenario_cfg,
+                  context_cfg, self.aborted, self.output_queue))
+        self.process.start()
diff --git a/yardstick/benchmark/runners/proxduration.py b/yardstick/benchmark/runners/proxduration.py
new file mode 100644 (file)
index 0000000..61a468f
--- /dev/null
@@ -0,0 +1,165 @@
+# Copyright 2014: Mirantis Inc.
+# All Rights Reserved.
+#
+#    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.
+
+# yardstick comment: this is a modified copy of
+# rally/rally/benchmark/runners/constant.py
+
+"""A runner that runs a specific time before it returns
+"""
+
+from __future__ import absolute_import
+
+import os
+import multiprocessing
+import logging
+import traceback
+import time
+
+from yardstick.benchmark.runners import base
+from yardstick.common import exceptions as y_exc
+from yardstick.common import constants
+
+LOG = logging.getLogger(__name__)
+
+def _worker_process(queue, cls, method_name, scenario_cfg,
+                    context_cfg, aborted, output_queue):
+
+    sequence = 1
+
+    runner_cfg = scenario_cfg['runner']
+
+    requested_interval = interval = runner_cfg.get("interval", 1)
+    duration = runner_cfg.get("duration", 60)
+    sampled = runner_cfg.get("sampled", False)
+
+    LOG.info("Worker START, duration is %ds", duration)
+    LOG.debug("class is %s", cls)
+
+    runner_cfg['runner_id'] = os.getpid()
+
+    benchmark = cls(scenario_cfg, context_cfg)
+    benchmark.setup()
+    method = getattr(benchmark, method_name)
+
+    sla_action = None
+    if "sla" in scenario_cfg:
+        sla_action = scenario_cfg["sla"].get("action", "assert")
+
+
+    start = time.time()
+    timeout = start + duration
+    while True:
+
+        LOG.debug("runner=%(runner)s seq=%(sequence)s START",
+                  {"runner": runner_cfg["runner_id"], "sequence": sequence})
+
+        data = {}
+        errors = ""
+
+        benchmark.pre_run_wait_time(interval)
+
+        if sampled:
+            try:
+                pre_adjustment = time.time()
+                result = method(data)
+                post_adjustment = time.time()
+                if requested_interval > post_adjustment - pre_adjustment:
+                    interval = requested_interval - (post_adjustment - pre_adjustment)
+                else:
+                    interval = 0
+
+            except y_exc.SLAValidationError as error:
+                # SLA validation failed in scenario, determine what to do now
+                if sla_action == "assert":
+                    raise
+                elif sla_action == "monitor":
+                    LOG.warning("SLA validation failed: %s", error.args)
+                    errors = error.args
+            # catch all exceptions because with multiprocessing we can have un-picklable exception
+            # problems  https://bugs.python.org/issue9400
+            except Exception:  # pylint: disable=broad-except
+                errors = traceback.format_exc()
+                LOG.exception("")
+            else:
+                if result:
+                    # add timeout for put so we don't block test
+                    # if we do timeout we don't care about dropping individual KPIs
+                    output_queue.put(result, True, constants.QUEUE_PUT_TIMEOUT)
+
+            benchmark_output = {
+                'timestamp': time.time(),
+                'sequence': sequence,
+                'data': data,
+                'errors': errors
+            }
+
+            queue.put(benchmark_output, True, constants.QUEUE_PUT_TIMEOUT)
+        else:
+            LOG.debug("No sample collected ...Sequence %s", sequence)
+
+
+        sequence += 1
+
+        if (errors and sla_action is None) or time.time() > timeout or aborted.is_set():
+            LOG.info("Worker END")
+            break
+
+    try:
+        benchmark.teardown()
+    except Exception:
+        # catch any exception in teardown and convert to simple exception
+        # never pass exceptions back to multiprocessing, because some exceptions can
+        # be unpicklable
+        # https://bugs.python.org/issue9400
+        LOG.exception("")
+        raise SystemExit(1)
+
+    LOG.debug("queue.qsize() = %s", queue.qsize())
+    LOG.debug("output_queue.qsize() = %s", output_queue.qsize())
+    LOG.info("Exiting ProxDuration Runner...")
+
+class ProxDurationRunner(base.Runner):
+    """Run a scenario for a certain amount of time
+
+If the scenario ends before the time has elapsed, it will be started again.
+
+  Parameters
+    duration - amount of time the scenario will be run for
+        type:    int
+        unit:    seconds
+        default: 60 sec
+    interval - time to wait between each scenario invocation
+        type:    int
+        unit:    seconds
+        default: 1 sec
+    sampled - Sample data is required yes/no
+        type:    boolean
+        unit:    True/False
+        default: False
+    confirmation - Number of confirmation retries
+        type:    int
+        unit:    retry attempts
+        default: 0
+    """
+    __execution_type__ = 'ProxDuration'
+
+    def _run_benchmark(self, cls, method, scenario_cfg, context_cfg):
+        name = "{}-{}-{}".format(self.__execution_type__, scenario_cfg.get("type"), os.getpid())
+        self.process = multiprocessing.Process(
+            name=name,
+            target=_worker_process,
+            args=(self.result_queue, cls, method, scenario_cfg,
+                  context_cfg, self.aborted, self.output_queue))
+        self.process.start()
index 8037329..01a4292 100644 (file)
@@ -33,6 +33,7 @@ from collections import Mapping
 from six.moves import zip
 
 from yardstick.benchmark.runners import base
+from yardstick.common import exceptions as y_exc
 
 LOG = logging.getLogger(__name__)
 
@@ -119,14 +120,14 @@ If the scenario ends before the time has elapsed, it will be started again.
 
         try:
             self.worker_helper(data)
-        except AssertionError as assertion:
+        except y_exc.SLAValidationError as error:
             # SLA validation failed in scenario, determine what to do now
             if self.sla_action == "assert":
                 raise
             elif self.sla_action == "monitor":
-                LOG.warning("SLA validation failed: %s", assertion.args)
-                errors = assertion.args
-        except Exception as e:
+                LOG.warning("SLA validation failed: %s", error.args)
+                errors = error.args
+        except Exception as e:  # pylint: disable=broad-except
             errors = traceback.format_exc()
             LOG.exception(e)
 
index d6e3f71..0148a45 100644 (file)
@@ -30,6 +30,7 @@ import traceback
 import os
 
 from yardstick.benchmark.runners import base
+from yardstick.common import exceptions as y_exc
 
 LOG = logging.getLogger(__name__)
 
@@ -74,14 +75,14 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
 
         try:
             result = method(data)
-        except AssertionError as assertion:
+        except y_exc.SLAValidationError as error:
             # SLA validation failed in scenario, determine what to do now
             if sla_action == "assert":
                 raise
             elif sla_action == "monitor":
-                LOG.warning("SLA validation failed: %s", assertion.args)
-                errors = assertion.args
-        except Exception as e:
+                LOG.warning("SLA validation failed: %s", error.args)
+                errors = error.args
+        except Exception as e:  # pylint: disable=broad-except
             errors = traceback.format_exc()
             LOG.exception(e)
         else:
index 1fadd25..e2db03a 100644 (file)
@@ -58,16 +58,20 @@ class ScenarioGeneral(base.Scenario):
         self.director.stopMonitors()
 
         verify_result = self.director.verify()
+        service_not_found = False
         for k, v in self.director.data.items():
             if v == 0:
-                result['sla_pass'] = 0
                 verify_result = False
+                service_not_found = True
                 LOG.info("\033[92m The service process (%s) not found in the host environment", k)
 
         result['sla_pass'] = 1 if verify_result else 0
         self.director.store_result(result)
 
-        assert verify_result is True, "The HA test case NOT passed"
+        self.verify_SLA(
+            verify_result, ("a service process was not found in the host "
+                            "environment" if service_not_found
+                            else "Director.verify() failed"))
 
     def teardown(self):
         self.director.knockoff()
index 42941c6..7f976fd 100755 (executable)
@@ -29,6 +29,7 @@ class ServiceHA(base.Scenario):
         self.context_cfg = context_cfg
         self.setup_done = False
         self.data = {}
+        self.sla_pass = False
 
     def setup(self):
         """scenario setup"""
@@ -69,23 +70,28 @@ class ServiceHA(base.Scenario):
         self.monitorMgr.wait_monitors()
         LOG.info("Monitor '%s' stop!", self.__scenario_type__)
 
-        sla_pass = self.monitorMgr.verify_SLA()
+        self.sla_pass = self.monitorMgr.verify_SLA()
+        service_not_found = False
         for k, v in self.data.items():
             if v == 0:
-                sla_pass = False
+                self.sla_pass = False
+                service_not_found = True
                 LOG.info("The service process (%s) not found in the host envrioment", k)
 
-        result['sla_pass'] = 1 if sla_pass else 0
+        result['sla_pass'] = 1 if self.sla_pass else 0
         self.monitorMgr.store_result(result)
 
-        assert sla_pass is True, "The HA test case NOT pass the SLA"
-
-        return
+        self.verify_SLA(
+            self.sla_pass, ("a service process was not found in the host "
+                            "environment" if service_not_found
+                            else "MonitorMgr.verify_SLA() failed"))
 
     def teardown(self):
         """scenario teardown"""
-        for attacker in self.attackers:
-            attacker.recover()
+        # only recover when sla not pass
+        if not self.sla_pass:
+            for attacker in self.attackers:
+                attacker.recover()
 
 
 def _test():    # pragma: no cover
index 58a0280..90a87ac 100644 (file)
@@ -20,6 +20,7 @@ import six
 from stevedore import extension
 
 import yardstick.common.utils as utils
+from yardstick.common import exceptions as y_exc
 
 
 def _iter_scenario_classes(scenario_type=None):
@@ -61,6 +62,11 @@ class Scenario(object):
         """Time waited after executing the run method"""
         time.sleep(time_seconds)
 
+    def verify_SLA(self, condition, error_msg):
+        if not condition:
+            raise y_exc.SLAValidationError(
+                case_name=self.__scenario_type__, error_msg=error_msg)
+
     @staticmethod
     def get_types():
         """return a list of known runner type (class) names"""
@@ -113,3 +119,7 @@ class Scenario(object):
             except TypeError:
                 dic[k] = v
         return dic
+
+    def get_mq_ids(self):  # pragma: no cover
+        """Return stored MQ producer IDs, if defined"""
+        pass
index 998463e..413709f 100644 (file)
@@ -100,7 +100,7 @@ class Cyclictest(base.Scenario):
 
     def _run_setup_cmd(self, client, cmd):
         LOG.debug("Run cmd: %s", cmd)
-        status, stdout, stderr = client.execute(cmd)
+        status, _, stderr = client.execute(cmd)
         if status:
             if re.search(self.REBOOT_CMD_PATTERN, cmd):
                 LOG.debug("Error on reboot")
@@ -195,7 +195,7 @@ class Cyclictest(base.Scenario):
                 if latency > sla_latency:
                     sla_error += "%s latency %d > sla:max_%s_latency(%d); " % \
                         (t, latency, t, sla_latency)
-            assert sla_error == "", sla_error
+            self.verify_SLA(sla_error == "", sla_error)
 
 
 def _test():    # pragma: no cover
index 801f7fa..2237e49 100644 (file)
@@ -119,8 +119,8 @@ class Lmbench(base.Scenario):
             cmd = "sudo bash lmbench_latency_for_cache.sh %d %d" % \
                   (repetition, warmup)
         else:
-            raise RuntimeError("No such test_type: %s for Lmbench scenario",
-                               test_type)
+            raise RuntimeError("No such test_type: %s for Lmbench scenario"
+                               test_type)
 
         LOG.debug("Executing command: %s", cmd)
         status, stdout, stderr = self.client.execute(cmd)
@@ -157,7 +157,7 @@ class Lmbench(base.Scenario):
                 if sla_latency < cache_latency:
                     sla_error += "latency %f > sla:max_latency(%f); " \
                         % (cache_latency, sla_latency)
-            assert sla_error == "", sla_error
+            self.verify_SLA(sla_error == "", sla_error)
 
 
 def _test():
index 0b8ed9b..b973211 100644 (file)
@@ -93,7 +93,7 @@ class Perf(base.Scenario):
             % (load, duration, events_string)
 
         LOG.debug("Executing command: %s", cmd)
-        status, stdout, stderr = self.client.execute(cmd)
+        status, stdout, _ = self.client.execute(cmd)
 
         if status:
             raise RuntimeError(stdout)
@@ -105,16 +105,14 @@ class Perf(base.Scenario):
             exp_val = self.scenario_cfg['sla']['expected_value']
             smaller_than_exp = 'smaller_than_expected' \
                                in self.scenario_cfg['sla']
-
-            if metric not in result:
-                assert False, "Metric (%s) not found." % metric
-            else:
-                if smaller_than_exp:
-                    assert result[metric] < exp_val, "%s %d >= %d (sla); " \
-                        % (metric, result[metric], exp_val)
-                else:
-                    assert result[metric] >= exp_val, "%s %d < %d (sla); " \
-                        % (metric, result[metric], exp_val)
+            self.verify_SLA(metric in result,
+                            "Metric (%s) not found." % metric)
+            self.verify_SLA(
+                not smaller_than_exp,
+                "%s %d >= %d (sla); " % (metric, result[metric], exp_val))
+            self.verify_SLA(
+                result[metric] >= exp_val,
+                "%s %d < %d (sla); " % (metric, result[metric], exp_val))
 
 
 def _test():
index 2de1270..975c90b 100644 (file)
@@ -56,7 +56,7 @@ class QemuMigrate(base.Scenario):
 
     def _run_setup_cmd(self, client, cmd):
         LOG.debug("Run cmd: %s", cmd)
-        status, stdout, stderr = client.execute(cmd)
+        status, _, stderr = client.execute(cmd)
         if status:
             if re.search(self.REBOOT_CMD_PATTERN, cmd):
                 LOG.debug("Error on reboot")
@@ -127,7 +127,7 @@ class QemuMigrate(base.Scenario):
                 if timevalue > sla_time:
                     sla_error += "%s timevalue %d > sla:max_%s(%d); " % \
                         (t, timevalue, t, sla_time)
-            assert sla_error == "", sla_error
+            self.verify_SLA(sla_error == "", sla_error)
 
 
 def _test():    # pragma: no cover
index ca64935..4daf776 100644 (file)
@@ -121,8 +121,8 @@ class Ramspeed(base.Scenario):
                   (test_id, load, block_size)
         # only the test_id 1-6 will be used in this scenario
         else:
-            raise RuntimeError("No such type_id: %s for Ramspeed scenario",
-                               test_id)
+            raise RuntimeError("No such type_id: %s for Ramspeed scenario"
+                               test_id)
 
         LOG.debug("Executing command: %s", cmd)
         status, stdout, stderr = self.client.execute(cmd)
@@ -140,4 +140,4 @@ class Ramspeed(base.Scenario):
                 if bw < sla_min_bw:
                     sla_error += "Bandwidth %f < " \
                         "sla:min_bandwidth(%f)" % (bw, sla_min_bw)
-            assert sla_error == "", sla_error
+            self.verify_SLA(sla_error == "", sla_error)
index cdb3457..3cea316 100644 (file)
@@ -125,7 +125,7 @@ class Unixbench(base.Scenario):
                 if score < sla_score:
                     sla_error += "%s score %f < sla:%s_score(%f); " % \
                         (t, score, t, sla_score)
-            assert sla_error == "", sla_error
+            self.verify_SLA(sla_error == "", sla_error)
 
 
 def _test():  # pragma: no cover
index 98c4599..51e044e 100644 (file)
@@ -92,7 +92,7 @@ For more info see http://software.es.net/iperf
     def teardown(self):
         LOG.debug("teardown")
         self.host.close()
-        status, stdout, stderr = self.target.execute("pkill iperf3")
+        status, _, stderr = self.target.execute("pkill iperf3")
         if status:
             LOG.warning(stderr)
         self.target.close()
@@ -145,7 +145,7 @@ For more info see http://software.es.net/iperf
 
         LOG.debug("Executing command: %s", cmd)
 
-        status, stdout, stderr = self.host.execute(cmd)
+        status, stdout, _ = self.host.execute(cmd)
         if status:
             # error cause in json dict on stdout
             raise RuntimeError(stdout)
@@ -165,16 +165,17 @@ For more info see http://software.es.net/iperf
                 bit_per_second = \
                     int(iperf_result["end"]["sum_received"]["bits_per_second"])
                 bytes_per_second = bit_per_second / 8
-                assert bytes_per_second >= sla_bytes_per_second, \
-                    "bytes_per_second %d < sla:bytes_per_second (%d); " % \
-                    (bytes_per_second, sla_bytes_per_second)
+                self.verify_SLA(
+                    bytes_per_second >= sla_bytes_per_second,
+                    "bytes_per_second %d < sla:bytes_per_second (%d); "
+                    % (bytes_per_second, sla_bytes_per_second))
             else:
                 sla_jitter = float(sla_iperf["jitter"])
 
                 jitter_ms = float(iperf_result["end"]["sum"]["jitter_ms"])
-                assert jitter_ms <= sla_jitter, \
-                    "jitter_ms  %f > sla:jitter %f; " % \
-                    (jitter_ms, sla_jitter)
+                self.verify_SLA(jitter_ms <= sla_jitter,
+                                "jitter_ms  %f > sla:jitter %f; "
+                                % (jitter_ms, sla_jitter))
 
 
 def _test():
index 86173c9..e3bd7af 100644 (file)
@@ -367,9 +367,10 @@ ports = {0,1},
             throughput_rx_mpps = int(
                 self.scenario_cfg["sla"]["throughput_rx_mpps"])
 
-            assert throughput_rx_mpps <= moongen_result["tx_mpps"], \
-                "sla_throughput_rx_mpps %f > throughput_rx_mpps(%f); " % \
-                (throughput_rx_mpps, moongen_result["tx_mpps"])
+            self.verify_SLA(
+                throughput_rx_mpps <= moongen_result["tx_mpps"],
+                "sla_throughput_rx_mpps %f > throughput_rx_mpps(%f); "
+                % (throughput_rx_mpps, moongen_result["tx_mpps"]))
 
     def teardown(self):
         """cleanup after the test execution"""
index 33c02d4..9f1a814 100755 (executable)
@@ -138,9 +138,9 @@ class Netperf(base.Scenario):
             sla_max_mean_latency = int(
                 self.scenario_cfg["sla"]["mean_latency"])
 
-            assert mean_latency <= sla_max_mean_latency, \
-                "mean_latency %f > sla_max_mean_latency(%f); " % \
-                (mean_latency, sla_max_mean_latency)
+            self.verify_SLA(mean_latency <= sla_max_mean_latency,
+                            "mean_latency %f > sla_max_mean_latency(%f); "
+                            % (mean_latency, sla_max_mean_latency))
 
 
 def _test():
index d52e6b9..0ad2ecf 100755 (executable)
@@ -156,9 +156,10 @@ class NetperfNode(base.Scenario):
             sla_max_mean_latency = int(
                 self.scenario_cfg["sla"]["mean_latency"])
 
-            assert mean_latency <= sla_max_mean_latency, \
-                "mean_latency %f > sla_max_mean_latency(%f); " % \
-                (mean_latency, sla_max_mean_latency)
+            self.verify_SLA(
+                mean_latency <= sla_max_mean_latency,
+                "mean_latency %f > sla_max_mean_latency(%f); "
+                % (mean_latency, sla_max_mean_latency))
 
     def teardown(self):
         """remove netperf from nodes after test"""
index 10c5607..ea067f8 100644 (file)
@@ -121,4 +121,4 @@ class Nstat(base.Scenario):
                 if rate > sla_rate:
                     sla_error += "%s rate %f > sla:%s_rate(%f); " % \
                         (i, rate, i, sla_rate)
-            assert sla_error == "", sla_error
+            self.verify_SLA(sla_error == "", sla_error)
index e7d9bee..6caeab5 100644 (file)
@@ -91,9 +91,10 @@ class Ping(base.Scenario):
                 result.update(utils.flatten_dict_key(ping_result))
                 if sla_max_rtt is not None:
                     sla_max_rtt = float(sla_max_rtt)
-                    assert rtt_result[target_vm_name] <= sla_max_rtt,\
-                        "rtt %f > sla: max_rtt(%f); " % \
-                        (rtt_result[target_vm_name], sla_max_rtt)
+                    self.verify_SLA(
+                        rtt_result[target_vm_name] <= sla_max_rtt,
+                        "rtt %f > sla: max_rtt(%f); "
+                        % (rtt_result[target_vm_name], sla_max_rtt))
             else:
                 LOG.error("ping '%s' '%s' timeout", options, target_vm)
                 # we need to specify a result to satisfy influxdb schema
@@ -102,13 +103,12 @@ class Ping(base.Scenario):
                 rtt_result[target_vm_name] = float(self.PING_ERROR_RTT)
                 # store result before potential AssertionError
                 result.update(utils.flatten_dict_key(ping_result))
-                if sla_max_rtt is not None:
-                    raise AssertionError("packet dropped rtt {:f} > sla: max_rtt({:f})".format(
-                        rtt_result[target_vm_name], sla_max_rtt))
-
-                else:
-                    raise AssertionError(
-                        "packet dropped rtt {:f}".format(rtt_result[target_vm_name]))
+                self.verify_SLA(sla_max_rtt is None,
+                                "packet dropped rtt %f > sla: max_rtt(%f)"
+                                % (rtt_result[target_vm_name], sla_max_rtt))
+                self.verify_SLA(False,
+                                "packet dropped rtt %f"
+                                % (rtt_result[target_vm_name]))
 
 
 def _test():    # pragma: no cover
index 74855a1..3772780 100644 (file)
@@ -59,8 +59,7 @@ class Ping6(base.Scenario):  # pragma: no cover
             self._ssh_host(node_name)
             self.client._put_file_shell(
                 self.pre_setup_script, '~/pre_setup.sh')
-            status, stdout, stderr = self.client.execute(
-                "sudo bash pre_setup.sh")
+            self.client.execute("sudo bash pre_setup.sh")
 
     def _get_controller_node(self, host_list):
         for host_name in host_list:
@@ -122,7 +121,7 @@ class Ping6(base.Scenario):  # pragma: no cover
         cmd = "sudo bash %s %s %s" % \
               (setup_bash_file, self.openrc, self.external_network)
         LOG.debug("Executing setup command: %s", cmd)
-        status, stdout, stderr = self.client.execute(cmd)
+        self.client.execute(cmd)
 
         self.setup_done = True
 
@@ -171,8 +170,9 @@ class Ping6(base.Scenario):  # pragma: no cover
             result["rtt"] = float(stdout)
             if "sla" in self.scenario_cfg:
                 sla_max_rtt = int(self.scenario_cfg["sla"]["max_rtt"])
-                assert result["rtt"] <= sla_max_rtt, \
-                    "rtt %f > sla:max_rtt(%f); " % (result["rtt"], sla_max_rtt)
+                self.verify_SLA(result["rtt"] <= sla_max_rtt,
+                                "rtt %f > sla:max_rtt(%f); "
+                                % (result["rtt"], sla_max_rtt))
         else:
             LOG.error("ping6 timeout!!!")
         self.run_done = True
@@ -216,5 +216,4 @@ class Ping6(base.Scenario):  # pragma: no cover
             self._ssh_host(node_name)
             self.client._put_file_shell(
                 self.post_teardown_script, '~/post_teardown.sh')
-            status, stdout, stderr = self.client.execute(
-                "sudo bash post_teardown.sh")
+            self.client.execute("sudo bash post_teardown.sh")
index b79b915..c78108a 100644 (file)
@@ -87,7 +87,7 @@ class Pktgen(base.Scenario):
         self.server.send_command(cmd)
         self.client.send_command(cmd)
 
-        """multiqueue setup"""
+        # multiqueue setup
         if not self._is_irqbalance_disabled():
             self._disable_irqbalance()
 
@@ -112,18 +112,14 @@ class Pktgen(base.Scenario):
     def _get_vnic_driver_name(self):
         cmd = "readlink /sys/class/net/%s/device/driver" % self.vnic_name
         LOG.debug("Executing command: %s", cmd)
-        status, stdout, stderr = self.server.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
         return os.path.basename(stdout.strip())
 
     def _is_irqbalance_disabled(self):
         """Did we disable irqbalance already in the guest?"""
         is_disabled = False
         cmd = "grep ENABLED /etc/default/irqbalance"
-        status, stdout, stderr = self.server.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
         if "0" in stdout:
             is_disabled = True
 
@@ -132,49 +128,35 @@ class Pktgen(base.Scenario):
     def _disable_irqbalance(self):
         cmd = "sudo sed -i -e 's/ENABLED=\"1\"/ENABLED=\"0\"/g' " \
               "/etc/default/irqbalance"
-        status, stdout, stderr = self.server.execute(cmd)
-        status, stdout, stderr = self.client.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        self.server.run(cmd)
+        self.client.run(cmd)
 
         cmd = "sudo service irqbalance stop"
-        status, stdout, stderr = self.server.execute(cmd)
-        status, stdout, stderr = self.client.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        self.server.run(cmd)
+        self.client.run(cmd)
 
         cmd = "sudo service irqbalance disable"
-        status, stdout, stderr = self.server.execute(cmd)
-        status, stdout, stderr = self.client.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        self.server.run(cmd)
+        self.client.run(cmd)
 
     def _setup_irqmapping_ovs(self, queue_number):
         cmd = "grep 'virtio0-input.0' /proc/interrupts |" \
               "awk '{match($0,/ +[0-9]+/)} " \
               "{print substr($1,RSTART,RLENGTH-1)}'"
-        status, stdout, stderr = self.server.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
 
         cmd = "echo 1 | sudo tee /proc/irq/%s/smp_affinity" % (int(stdout))
-        status, stdout, stderr = self.server.execute(cmd)
-        status, stdout, stderr = self.client.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        self.server.run(cmd)
+        self.client.run(cmd)
 
         cmd = "grep 'virtio0-output.0' /proc/interrupts |" \
               "awk '{match($0,/ +[0-9]+/)} " \
               "{print substr($1,RSTART,RLENGTH-1)}'"
-        status, stdout, stderr = self.server.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
 
         cmd = "echo 1 | sudo tee /proc/irq/%s/smp_affinity" % (int(stdout))
-        status, stdout, stderr = self.server.execute(cmd)
-        status, stdout, stderr = self.client.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        self.server.run(cmd)
+        self.client.run(cmd)
 
         if queue_number == 1:
             return
@@ -186,44 +168,32 @@ class Pktgen(base.Scenario):
             cmd = "grep 'virtio0-input.%s' /proc/interrupts |" \
                   "awk '{match($0,/ +[0-9]+/)} " \
                   "{print substr($1,RSTART,RLENGTH-1)}'" % (i)
-            status, stdout, stderr = self.server.execute(cmd)
-            if status:
-                raise RuntimeError(stderr)
+            _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
 
             cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \
                 % (smp_affinity_mask, int(stdout))
-            status, stdout, stderr = self.server.execute(cmd)
-            status, stdout, stderr = self.client.execute(cmd)
-            if status:
-                raise RuntimeError(stderr)
+            self.server.run(cmd)
+            self.client.run(cmd)
 
             cmd = "grep 'virtio0-output.%s' /proc/interrupts |" \
                   "awk '{match($0,/ +[0-9]+/)} " \
                   "{print substr($1,RSTART,RLENGTH-1)}'" % (i)
-            status, stdout, stderr = self.server.execute(cmd)
-            if status:
-                raise RuntimeError(stderr)
+            _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
 
             cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \
                 % (smp_affinity_mask, int(stdout))
-            status, stdout, stderr = self.server.execute(cmd)
-            status, stdout, stderr = self.client.execute(cmd)
-            if status:
-                raise RuntimeError(stderr)
+            self.server.run(cmd)
+            self.client.run(cmd)
 
     def _setup_irqmapping_sriov(self, queue_number):
         cmd = "grep '%s-TxRx-0' /proc/interrupts |" \
               "awk '{match($0,/ +[0-9]+/)} " \
               "{print substr($1,RSTART,RLENGTH-1)}'" % self.vnic_name
-        status, stdout, stderr = self.server.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
 
         cmd = "echo 1 | sudo tee /proc/irq/%s/smp_affinity" % (int(stdout))
-        status, stdout, stderr = self.server.execute(cmd)
-        status, stdout, stderr = self.client.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        self.server.run(cmd)
+        self.client.run(cmd)
 
         if queue_number == 1:
             return
@@ -234,24 +204,18 @@ class Pktgen(base.Scenario):
             cmd = "grep '%s-TxRx-%s' /proc/interrupts |" \
                   "awk '{match($0,/ +[0-9]+/)} " \
                   "{print substr($1,RSTART,RLENGTH-1)}'" % (self.vnic_name, i)
-            status, stdout, stderr = self.server.execute(cmd)
-            if status:
-                raise RuntimeError(stderr)
+            _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
 
             cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \
                 % (smp_affinity_mask, int(stdout))
-            status, stdout, stderr = self.server.execute(cmd)
-            status, stdout, stderr = self.client.execute(cmd)
-            if status:
-                raise RuntimeError(stderr)
+            self.server.run(cmd)
+            self.client.run(cmd)
 
     def _get_sriov_queue_number(self):
         """Get queue number from server as both VMs are the same"""
         cmd = "grep %s-TxRx- /proc/interrupts | wc -l" % self.vnic_name
         LOG.debug("Executing command: %s", cmd)
-        status, stdout, stderr = self.server.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
         return int(stdout)
 
     def _get_available_queue_number(self):
@@ -259,9 +223,7 @@ class Pktgen(base.Scenario):
         cmd = "sudo ethtool -l %s | grep Combined | head -1 |" \
               "awk '{printf $2}'" % self.vnic_name
         LOG.debug("Executing command: %s", cmd)
-        status, stdout, stderr = self.server.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
         return int(stdout)
 
     def _get_usable_queue_number(self):
@@ -269,9 +231,7 @@ class Pktgen(base.Scenario):
         cmd = "sudo ethtool -l %s | grep Combined | tail -1 |" \
               "awk '{printf $2}'" % self.vnic_name
         LOG.debug("Executing command: %s", cmd)
-        status, stdout, stderr = self.server.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
         return int(stdout)
 
     def _enable_ovs_multiqueue(self):
@@ -282,10 +242,8 @@ class Pktgen(base.Scenario):
             cmd = "sudo ethtool -L %s combined %s" % \
                 (self.vnic_name, available_queue_number)
             LOG.debug("Executing command: %s", cmd)
-            status, stdout, stderr = self.server.execute(cmd)
-            status, stdout, stderr = self.client.execute(cmd)
-            if status:
-                raise RuntimeError(stderr)
+            self.server.run(cmd)
+            self.client.run(cmd)
         return available_queue_number
 
     def _iptables_setup(self):
@@ -294,9 +252,7 @@ class Pktgen(base.Scenario):
               "sudo iptables -A INPUT -p udp --dport 1000:%s -j DROP" \
               % (1000 + self.number_of_ports)
         LOG.debug("Executing command: %s", cmd)
-        status, _, stderr = self.server.execute(cmd, timeout=SSH_TIMEOUT)
-        if status:
-            raise RuntimeError(stderr)
+        self.server.run(cmd, timeout=SSH_TIMEOUT)
 
     def _iptables_get_result(self):
         """Get packet statistics from server"""
@@ -304,9 +260,7 @@ class Pktgen(base.Scenario):
               "awk '/dpts:1000:%s/ {{printf \"%%s\", $1}}'" \
               % (1000 + self.number_of_ports)
         LOG.debug("Executing command: %s", cmd)
-        status, stdout, stderr = self.server.execute(cmd)
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.server.execute(cmd, raise_on_error=True)
         return int(stdout)
 
     def run(self, result):
@@ -356,10 +310,8 @@ class Pktgen(base.Scenario):
                duration, queue_number, pps)
 
         LOG.debug("Executing command: %s", cmd)
-        status, stdout, stderr = self.client.execute(cmd, timeout=SSH_TIMEOUT)
-
-        if status:
-            raise RuntimeError(stderr)
+        _, stdout, _ = self.client.execute(cmd, raise_on_error=True,
+                                           timeout=SSH_TIMEOUT)
 
         result.update(jsonutils.loads(stdout))
 
@@ -374,8 +326,8 @@ class Pktgen(base.Scenario):
         if "sla" in self.scenario_cfg:
             LOG.debug("Lost packets %d - Lost ppm %d", (sent - received), ppm)
             sla_max_ppm = int(self.scenario_cfg["sla"]["max_ppm"])
-            assert ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d; " \
-                % (ppm, sla_max_ppm)
+            self.verify_SLA(ppm <= sla_max_ppm,
+                            "ppm %d > sla_max_ppm %d; " % (ppm, sla_max_ppm))
 
 
 def _test():  # pragma: no cover
index 9a7b975..efb7d8b 100644 (file)
@@ -113,10 +113,7 @@ cat ~/result.log -vT \
 {print substr($0,RSTART,RLENGTH)}' \
 |grep -v ^$ |awk '{if ($2 != 0) print $2}'\
 """
-        client_status, client_stdout, client_stderr = self.client.execute(cmd)
-
-        if client_status:
-            raise RuntimeError(client_stderr)
+        _, client_stdout, _ = self.client.execute(cmd, raise_on_error=True)
 
         avg_latency = 0
         if client_stdout:
@@ -135,4 +132,4 @@ cat ~/result.log -vT \
             LOG.info("sla_max_latency: %d", sla_max_latency)
             debug_info = "avg_latency %d > sla_max_latency %d" \
                 % (avg_latency, sla_max_latency)
-            assert avg_latency <= sla_max_latency, debug_info
+            self.verify_SLA(avg_latency <= sla_max_latency, debug_info)
index 497e59e..97b9cf7 100644 (file)
@@ -143,11 +143,11 @@ class PktgenDPDK(base.Scenario):
         cmd = "ip a | grep eth1 2>/dev/null"
         LOG.debug("Executing command: %s in %s", cmd, host)
         if "server" in host:
-            status, stdout, stderr = self.server.execute(cmd)
+            _, stdout, _ = self.server.execute(cmd)
             if stdout:
                 is_run = False
         else:
-            status, stdout, stderr = self.client.execute(cmd)
+            _, stdout, _ = self.client.execute(cmd)
             if stdout:
                 is_run = False
 
@@ -222,5 +222,5 @@ class PktgenDPDK(base.Scenario):
             ppm += (sent - received) % sent > 0
             LOG.debug("Lost packets %d - Lost ppm %d", (sent - received), ppm)
             sla_max_ppm = int(self.scenario_cfg["sla"]["max_ppm"])
-            assert ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d; " \
-                % (ppm, sla_max_ppm)
+            self.verify_SLA(ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d; "
+                                                % (ppm, sla_max_ppm))
index 1c3ea1f..3bb168c 100644 (file)
@@ -23,6 +23,7 @@ import time
 import six
 import yaml
 
+from yardstick.benchmark.contexts import base as context_base
 from yardstick.benchmark.scenarios import base as scenario_base
 from yardstick.common.constants import LOG_DIR
 from yardstick.common import exceptions
@@ -36,6 +37,7 @@ from yardstick.network_services.traffic_profile import base as tprofile_base
 from yardstick.network_services.utils import get_nsb_option
 from yardstick import ssh
 
+
 traffic_profile.register_modules()
 
 
@@ -48,7 +50,7 @@ class NetworkServiceTestCase(scenario_base.Scenario):
 
     __scenario_type__ = "NSPerf"
 
-    def __init__(self, scenario_cfg, context_cfg):  # Yardstick API
+    def __init__(self, scenario_cfg, context_cfg):  # pragma: no cover
         super(NetworkServiceTestCase, self).__init__()
         self.scenario_cfg = scenario_cfg
         self.context_cfg = context_cfg
@@ -59,6 +61,7 @@ class NetworkServiceTestCase(scenario_base.Scenario):
         self.traffic_profile = None
         self.node_netdevs = {}
         self.bin_path = get_nsb_option('bin_path', '')
+        self._mq_ids = []
 
     def _get_ip_flow_range(self, ip_start_range):
 
@@ -133,11 +136,10 @@ class NetworkServiceTestCase(scenario_base.Scenario):
         with utils.open_relative_file(profile, path) as infile:
             return infile.read()
 
-    def _get_topology(self):
-        topology = self.scenario_cfg["topology"]
-        path = self.scenario_cfg["task_path"]
-        with utils.open_relative_file(topology, path) as infile:
-            return infile.read()
+    def _get_duration(self):
+        options = self.scenario_cfg.get('options', {})
+        return options.get('duration',
+                           tprofile_base.TrafficProfileConfig.DEFAULT_DURATION)
 
     def _fill_traffic_profile(self):
         tprofile = self._get_traffic_profile()
@@ -147,12 +149,17 @@ class NetworkServiceTestCase(scenario_base.Scenario):
             'imix': self._get_traffic_imix(),
             tprofile_base.TrafficProfile.UPLINK: {},
             tprofile_base.TrafficProfile.DOWNLINK: {},
-            'extra_args': extra_args
-        }
-
+            'extra_args': extra_args,
+            'duration': self._get_duration()}
         traffic_vnfd = vnfdgen.generate_vnfd(tprofile, tprofile_data)
         self.traffic_profile = tprofile_base.TrafficProfile.get(traffic_vnfd)
 
+    def _get_topology(self):
+        topology = self.scenario_cfg["topology"]
+        path = self.scenario_cfg["task_path"]
+        with utils.open_relative_file(topology, path) as infile:
+            return infile.read()
+
     def _render_topology(self):
         topology = self._get_topology()
         topology_args = self.scenario_cfg.get('extra_args', {})
@@ -162,18 +169,18 @@ class NetworkServiceTestCase(scenario_base.Scenario):
         topology_yaml = vnfdgen.generate_vnfd(topology, topolgy_data)
         self.topology = topology_yaml["nsd:nsd-catalog"]["nsd"][0]
 
-    def _find_vnf_name_from_id(self, vnf_id):
+    def _find_vnf_name_from_id(self, vnf_id):  # pragma: no cover
         return next((vnfd["vnfd-id-ref"]
                      for vnfd in self.topology["constituent-vnfd"]
                      if vnf_id == vnfd["member-vnf-index"]), None)
 
-    def _find_vnfd_from_vnf_idx(self, vnf_id):
+    def _find_vnfd_from_vnf_idx(self, vnf_id):  # pragma: no cover
         return next((vnfd
                      for vnfd in self.topology["constituent-vnfd"]
                      if vnf_id == vnfd["member-vnf-index"]), None)
 
     @staticmethod
-    def find_node_if(nodes, name, if_name, vld_id):
+    def find_node_if(nodes, name, if_name, vld_id):  # pragma: no cover
         try:
             # check for xe0, xe1
             intf = nodes[name]["interfaces"][if_name]
@@ -266,14 +273,14 @@ class NetworkServiceTestCase(scenario_base.Scenario):
             node0_if["peer_intf"] = node1_copy
             node1_if["peer_intf"] = node0_copy
 
-    def _update_context_with_topology(self):
+    def _update_context_with_topology(self):  # pragma: no cover
         for vnfd in self.topology["constituent-vnfd"]:
             vnf_idx = vnfd["member-vnf-index"]
             vnf_name = self._find_vnf_name_from_id(vnf_idx)
             vnfd = self._find_vnfd_from_vnf_idx(vnf_idx)
             self.context_cfg["nodes"][vnf_name].update(vnfd)
 
-    def _generate_pod_yaml(self):
+    def _generate_pod_yaml(self):  # pragma: no cover
         context_yaml = os.path.join(LOG_DIR, "pod-{}.yaml".format(self.scenario_cfg['task_id']))
         # convert OrderedDict to a list
         # pod.yaml nodes is a list
@@ -287,7 +294,7 @@ class NetworkServiceTestCase(scenario_base.Scenario):
                            explicit_start=True)
 
     @staticmethod
-    def _serialize_node(node):
+    def _serialize_node(node):  # pragma: no cover
         new_node = copy.deepcopy(node)
         # name field is required
         # remove context suffix
@@ -309,7 +316,7 @@ class NetworkServiceTestCase(scenario_base.Scenario):
         self._update_context_with_topology()
 
     @classmethod
-    def get_vnf_impl(cls, vnf_model_id):
+    def get_vnf_impl(cls, vnf_model_id):  # pragma: no cover
         """ Find the implementing class from vnf_model["vnf"]["name"] field
 
         :param vnf_model_id: parsed vnfd model ID field
@@ -337,7 +344,7 @@ class NetworkServiceTestCase(scenario_base.Scenario):
         raise exceptions.IncorrectConfig(error_msg=message)
 
     @staticmethod
-    def create_interfaces_from_node(vnfd, node):
+    def create_interfaces_from_node(vnfd, node):  # pragma: no cover
         ext_intfs = vnfd["vdu"][0]["external-interface"] = []
         # have to sort so xe0 goes first
         for intf_name, intf in sorted(node['interfaces'].items()):
@@ -406,10 +413,7 @@ class NetworkServiceTestCase(scenario_base.Scenario):
         return vnfs
 
     def setup(self):
-        """ Setup infrastructure, provission VNFs & start traffic
-
-        :return:
-        """
+        """Setup infrastructure, provission VNFs & start traffic"""
         # 1. Verify if infrastructure mapping can meet topology
         self.map_topology_to_infrastructure()
         # 1a. Load VNF models
@@ -444,13 +448,18 @@ class NetworkServiceTestCase(scenario_base.Scenario):
             traffic_gen.listen_traffic(self.traffic_profile)
 
         # register collector with yardstick for KPI collection.
-        self.collector = Collector(self.vnfs)
+        self.collector = Collector(self.vnfs, context_base.Context.get_physical_nodes())
         self.collector.start()
 
         # Start the actual traffic
         for traffic_gen in traffic_runners:
             LOG.info("Starting traffic on %s", traffic_gen.name)
             traffic_gen.run_traffic(self.traffic_profile)
+            self._mq_ids.append(traffic_gen.get_mq_producer_id())
+
+    def get_mq_ids(self):  # pragma: no cover
+        """Return stored MQ producer IDs"""
+        return self._mq_ids
 
     def run(self, result):  # yardstick API
         """ Yardstick calls run() at intervals defined in the yaml and
@@ -489,10 +498,10 @@ class NetworkServiceTestCase(scenario_base.Scenario):
             LOG.exception("")
             raise RuntimeError("Error in teardown")
 
-    def pre_run_wait_time(self, time_seconds):
+    def pre_run_wait_time(self, time_seconds):  # pragma: no cover
         """Time waited before executing the run method"""
         time.sleep(time_seconds)
 
-    def post_run_wait_time(self, time_seconds):
+    def post_run_wait_time(self, time_seconds):  # pragma: no cover
         """Time waited after executing the run method"""
         pass
index 705544c..2b34740 100644 (file)
@@ -215,15 +215,15 @@ class Vsperf(base.Scenario):
         if 'sla' in self.scenario_cfg and \
            'metrics' in self.scenario_cfg['sla']:
             for metric in self.scenario_cfg['sla']['metrics'].split(','):
-                assert metric in result, \
-                    '%s is not collected by VSPERF' % (metric)
-                assert metric in self.scenario_cfg['sla'], \
-                    '%s is not defined in SLA' % (metric)
+                self.verify_SLA(metric in result,
+                                '%s was not collected by VSPERF' % metric)
+                self.verify_SLA(metric in self.scenario_cfg['sla'],
+                                '%s is not defined in SLA' % metric)
                 vs_res = float(result[metric])
                 sla_res = float(self.scenario_cfg['sla'][metric])
-                assert vs_res >= sla_res, \
-                    'VSPERF_%s(%f) < SLA_%s(%f)' % \
-                    (metric, vs_res, metric, sla_res)
+                self.verify_SLA(vs_res >= sla_res,
+                                'VSPERF_%s(%f) < SLA_%s(%f)'
+                                % (metric, vs_res, metric, sla_res))
 
     def teardown(self):
         """cleanup after the test execution"""
index 4545878..27bf40d 100644 (file)
@@ -231,7 +231,7 @@ class VsperfDPDK(base.Scenario):
         is_run = True
         cmd = "ip a | grep %s 2>/dev/null" % (self.tg_port1)
         LOG.debug("Executing command: %s", cmd)
-        status, stdout, stderr = self.client.execute(cmd)
+        _, stdout, _ = self.client.execute(cmd)
         if stdout:
             is_run = False
         return is_run
@@ -325,15 +325,15 @@ class VsperfDPDK(base.Scenario):
         if 'sla' in self.scenario_cfg and \
            'metrics' in self.scenario_cfg['sla']:
             for metric in self.scenario_cfg['sla']['metrics'].split(','):
-                assert metric in result, \
-                    '%s is not collected by VSPERF' % (metric)
-                assert metric in self.scenario_cfg['sla'], \
-                    '%s is not defined in SLA' % (metric)
+                self.verify_SLA(metric in result,
+                                '%s was not collected by VSPERF' % metric)
+                self.verify_SLA(metric in self.scenario_cfg['sla'],
+                                '%s is not defined in SLA' % metric)
                 vs_res = float(result[metric])
                 sla_res = float(self.scenario_cfg['sla'][metric])
-                assert vs_res >= sla_res, \
-                    'VSPERF_%s(%f) < SLA_%s(%f)' % \
-                    (metric, vs_res, metric, sla_res)
+                self.verify_SLA(vs_res >= sla_res,
+                                'VSPERF_%s(%f) < SLA_%s(%f)'
+                                % (metric, vs_res, metric, sla_res))
 
     def teardown(self):
         """cleanup after the test execution"""
index d3ed840..c57c6ed 100644 (file)
@@ -223,7 +223,7 @@ class Fio(base.Scenario):
                         sla_error += "%s %d < " \
                             "sla:%s(%d); " % (k, v, k, min_v)
 
-            assert sla_error == "", sla_error
+            self.verify_SLA(sla_error == "", sla_error)
 
 
 def _test():
index 954e592..2f14d4b 100644 (file)
@@ -119,6 +119,7 @@ INFLUXDB_DB_NAME = get_param('influxdb.db_name', 'yardstick')
 INFLUXDB_IMAGE = get_param('influxdb.image', 'tutum/influxdb')
 INFLUXDB_TAG = get_param('influxdb.tag', '0.13')
 INFLUXDB_DASHBOARD_PORT = 8083
+QUEUE_PUT_TIMEOUT = 10
 
 # grafana
 GRAFANA_IP = get_param('grafana.ip', SERVER_IP)
index 2005beb..50def06 100644 (file)
@@ -70,6 +70,10 @@ class ResourceCommandError(YardstickException):
     message = 'Command: "%(command)s" Failed, stderr: "%(stderr)s"'
 
 
+class ContextUpdateCollectdForNodeError(YardstickException):
+    message = 'Cannot find node %(attr_name)s'
+
+
 class FunctionNotImplemented(YardstickException):
     message = ('The function "%(function_name)s" is not implemented in '
                '"%(class_name)" class.')
@@ -170,7 +174,7 @@ class IncorrectNodeSetup(IncorrectSetup):
 
 
 class ScenarioConfigContextNameNotFound(YardstickException):
-    message = 'Context name "%(context_name)s" not found'
+    message = 'Context for host name "%(host_name)s" not found'
 
 
 class StackCreationInterrupt(YardstickException):
@@ -189,6 +193,15 @@ class TaskRenderError(YardstickException):
     message = 'Failed to render template:\n%(input_task)s'
 
 
+class RunnerIterationIPCSetupActionNeeded(YardstickException):
+    message = ('IterationIPC needs the "setup" action to retrieve the VNF '
+               'handling processes PIDs to receive the messages sent')
+
+
+class RunnerIterationIPCNoCtxs(YardstickException):
+    message = 'Benchmark "setup" action did not return any VNF process PID'
+
+
 class TimerTimeout(YardstickException):
     message = 'Timer timeout expired, %(timeout)s seconds'
 
@@ -338,3 +351,16 @@ class IxNetworkFlowNotPresent(YardstickException):
 
 class IxNetworkFieldNotPresentInStackItem(YardstickException):
     message = 'Field "%(field_name)s" not present in stack item %(stack_item)s'
+
+
+class SLAValidationError(YardstickException):
+    message = '%(case_name)s SLA validation failed. Error: %(error_msg)s'
+
+
+class AclMissingActionArguments(YardstickException):
+    message = ('Missing ACL action parameter '
+               '[action=%(action_name)s parameter=%(action_param)s]')
+
+
+class AclUknownActionTemplate(YardstickException):
+    message = 'No ACL CLI template found for "%(action_name)s" action'
index f0f012e..bd700d9 100644 (file)
@@ -1,14 +1,3 @@
-# Copyright (c) 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.
 
@@ -28,9 +17,17 @@ TRANSPORT_URL = (MQ_SERVICE + '://' + MQ_USER + ':' + MQ_PASS + '@' + SERVER +
 RPC_SERVER_EXECUTOR = 'threading'
 
 # Topics.
-RUNNER = 'runner'
+TOPIC_TG = 'topic_traffic_generator'
+TOPIC_RUNNER = 'topic_runner'
 
 # Methods.
-# RUNNER methods:
-RUNNER_INFO = 'runner_info'
-RUNNER_LOOP = 'runner_loop'
+# Traffic generator consumers methods. Names must match the methods implemented
+# in the consumer endpoint class.
+TG_METHOD_STARTED = 'tg_method_started'
+TG_METHOD_FINISHED = 'tg_method_finished'
+TG_METHOD_ITERATION = 'tg_method_iteration'
+
+# Runner consumers methods. Names must match the methods implemented in the
+# consumer endpoint class.
+RUNNER_METHOD_START_ITERATION = "runner_method_start_iteration"
+RUNNER_METHOD_STOP_ITERATION = "runner_method_stop_iteration"
index 24ec6f1..c99d7ed 100644 (file)
@@ -29,9 +29,9 @@ LOG = logging.getLogger(__name__)
 class NotificationHandler(object):
     """Abstract class to define a endpoint object for a MessagingConsumer"""
 
-    def __init__(self, _id, ctx_pids, queue):
+    def __init__(self, _id, ctx_ids, queue):
         self._id = _id
-        self._ctx_pids = ctx_pids
+        self._ctx_ids = ctx_ids
         self._queue = queue
 
 
@@ -43,11 +43,11 @@ class MessagingConsumer(object):
     the messages published by a `MessagingNotifier`.
     """
 
-    def __init__(self, topic, pids, endpoints, fanout=True):
+    def __init__(self, topic, ids, endpoints, fanout=True):
         """Init function.
 
         :param topic: (string) MQ exchange topic
-        :param pids: (list of int) list of PIDs of the processes implementing
+        :param ids: (list of int) list of IDs of the processes implementing
                      the MQ Notifier which will be in the message context
         :param endpoints: (list of class) list of classes implementing the
                           methods (see `MessagingNotifier.send_message) used by
@@ -58,7 +58,7 @@ class MessagingConsumer(object):
         :returns: `MessagingConsumer` class object
         """
 
-        self._pids = pids
+        self._ids = ids
         self._endpoints = endpoints
         self._transport = oslo_messaging.get_rpc_transport(
             cfg.CONF, url=messaging.TRANSPORT_URL)
index d29d798..8ede1e5 100644 (file)
@@ -51,3 +51,23 @@ class Payload(object):
     def dict_to_obj(cls, _dict):
         """Returns a Payload object built from the dictionary elements"""
         return cls(**_dict)
+
+
+class TrafficGeneratorPayload(Payload):
+    """Base traffic generator payload class"""
+    REQUIRED_FIELDS = {
+        'version',  # (str) version of the payload transmitted.
+        'iteration',  # (int) iteration index during the traffic injection,
+                      # starting from 1.
+        'kpi'  # (dict) collection of KPIs collected from the traffic
+               # injection. The content will depend on the generator and the
+               # traffic type.
+    }
+
+
+class RunnerPayload(Payload):
+    """Base runner payload class"""
+    REQUIRED_FIELDS = {
+        'version',  # (str) version of the payload transmitted.
+        'data'  # (dict) generic container of data to be used if needed.
+    }
index b6adc0c..aadab64 100644 (file)
@@ -34,18 +34,18 @@ class MessagingProducer(object):
     messages in a message queue.
     """
 
-    def __init__(self, topic, pid=os.getpid(), fanout=True):
+    def __init__(self, topic, _id=os.getpid(), fanout=True):
         """Init function.
 
         :param topic: (string) MQ exchange topic
-        :param pid: (int) PID of the process implementing this MQ Notifier
+        :param id: (int) ID of the process implementing this MQ Notifier
         :param fanout: (bool) MQ clients may request that a copy of the message
                        be delivered to all servers listening on a topic by
                        setting fanout to ``True``, rather than just one of them
         :returns: `MessagingNotifier` class object
         """
         self._topic = topic
-        self._pid = pid
+        self._id = _id
         self._fanout = fanout
         self._transport = oslo_messaging.get_rpc_transport(
             cfg.CONF, url=messaging.TRANSPORT_URL)
@@ -65,6 +65,11 @@ class MessagingProducer(object):
                        consumer endpoints
         :param payload: (subclass `Payload`) payload content
         """
-        self._notifier.cast({'pid': self._pid},
+        self._notifier.cast({'id': self._id},
                             method,
                             **payload.obj_to_dict())
+
+    @property
+    def id(self):
+        """Return MQ producer ID"""
+        return self._id
index 6ff6617..5410613 100644 (file)
@@ -172,6 +172,15 @@ def get_shade_client(**os_cloud_config):
     params.update(os_cloud_config)
     return shade.openstack_cloud(**params)
 
+def get_shade_operator_client(**os_cloud_config):
+    """Get Shade Operator cloud client
+
+    :return: ``shade.OperatorCloud`` object.
+    """
+    params = copy.deepcopy(constants.OS_CLOUD_DEFAULT_CONFIG)
+    params.update(os_cloud_config)
+    return shade.operator_cloud(**params)
+
 
 # *********************************************
 #   NOVA
index 958ec62..85cecc7 100644 (file)
@@ -306,6 +306,19 @@ def get_ip_version(ip_addr):
         return address.version
 
 
+def make_ip_addr(ip, mask):
+    """
+    :param ip[str]: ip adddress
+    :param mask[str]: /24 prefix of 255.255.255.0 netmask
+    :return: IPv4Interface object
+    """
+    try:
+        return ipaddress.ip_interface(six.text_type('/'.join([ip, mask])))
+    except (TypeError, ValueError):
+        # None so we can skip later
+        return None
+
+
 def ip_to_hex(ip_addr, separator=''):
     try:
         address = ipaddress.ip_address(six.text_type(ip_addr))
@@ -409,13 +422,18 @@ class ErrorClass(object):
 
 
 class Timer(object):
-    def __init__(self, timeout=None):
+    def __init__(self, timeout=None, raise_exception=True):
         super(Timer, self).__init__()
         self.start = self.delta = None
         self._timeout = int(timeout) if timeout else None
+        self._timeout_flag = False
+        self._raise_exception = raise_exception
 
     def _timeout_handler(self, *args):
-        raise exceptions.TimerTimeout(timeout=self._timeout)
+        self._timeout_flag = True
+        if self._raise_exception:
+            raise exceptions.TimerTimeout(timeout=self._timeout)
+        self.__exit__()
 
     def __enter__(self):
         self.start = datetime.datetime.now()
@@ -432,6 +450,23 @@ class Timer(object):
     def __getattr__(self, item):
         return getattr(self.delta, item)
 
+    def __iter__(self):
+        self._raise_exception = False
+        return self.__enter__()
+
+    def next(self):  # pragma: no cover
+        # NOTE(ralonsoh): Python 2 support.
+        if not self._timeout_flag:
+            return datetime.datetime.now()
+        raise StopIteration()
+
+    def __next__(self):  # pragma: no cover
+        # NOTE(ralonsoh): Python 3 support.
+        return self.next()
+
+    def __del__(self):  # pragma: no cover
+        signal.alarm(0)
+
 
 def read_meminfo(ssh_client):
     """Read "/proc/meminfo" file and parse all keys and values"""
index 0572bd5..18673be 100644 (file)
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-# yardstick: this file is copied from python-heatclient and slightly modified
-
-from __future__ import absolute_import
-
 import yaml
 
 
@@ -23,6 +19,7 @@ if hasattr(yaml, 'CSafeLoader'):
 else:
     yaml_loader = type('CustomLoader', (yaml.SafeLoader,), {})
 
+
 if hasattr(yaml, 'CSafeDumper'):
     yaml_dumper = yaml.CSafeDumper
 else:
@@ -31,3 +28,10 @@ else:
 
 def yaml_load(tmpl_str):
     return yaml.load(tmpl_str, Loader=yaml_loader)
+
+
+def read_yaml_file(path):
+    """Read yaml file"""
+    with open(path) as stream:
+        data = yaml_load(stream)
+        return data
index 322b3f5..937c266 100644 (file)
 """This module implements stub for publishing results in yardstick format."""
 import logging
 
+from yardstick.network_services.nfvi.resource import ResourceProfile
+from yardstick.network_services.utils import get_nsb_option
+
+
 LOG = logging.getLogger(__name__)
 
 
 class Collector(object):
     """Class that handles dictionary of results in yardstick-plot format."""
 
-    def __init__(self, vnfs):
+    def __init__(self, vnfs, contexts_nodes, timeout=3600):
         super(Collector, self).__init__()
         self.vnfs = vnfs
+        self.nodes = contexts_nodes
+        self.bin_path = get_nsb_option('bin_path', '')
+        self.resource_profiles = {}
+
+        for ctx_name, nodes in contexts_nodes.items():
+            for node in (node for node in nodes if node.get('collectd')):
+                name = ".".join([node['name'], ctx_name])
+                self.resource_profiles.update(
+                    {name: ResourceProfile.make_from_node(node, timeout)}
+                    )
 
     def start(self):
+        for resource in self.resource_profiles.values():
+            resource.initiate_systemagent(self.bin_path)
+            resource.start()
+            resource.amqp_process_for_nfvi_kpi()
+
         for vnf in self.vnfs:
             vnf.start_collect()
 
@@ -32,6 +51,9 @@ class Collector(object):
         for vnf in self.vnfs:
             vnf.stop_collect()
 
+        for resource in self.resource_profiles.values():
+            resource.stop()
+
     def get_kpi(self):
         """Returns dictionary of results in yardstick-plot format
 
@@ -42,7 +64,12 @@ class Collector(object):
         for vnf in self.vnfs:
             # Result example:
             # {"VNF1: { "tput" : [1000, 999] }, "VNF2": { "latency": 100 }}
-            LOG.debug("collect KPI for %s", vnf.name)
+            LOG.debug("collect KPI for vnf %s", vnf.name)
             results[vnf.name] = vnf.collect_kpi()
 
+        for node_name, resource in self.resource_profiles.items():
+            LOG.debug("collect KPI for nfvi_node %s", node_name)
+            results[node_name] = {"core": resource.amqp_collect_nfvi_kpi()}
+            LOG.debug("%s collect KPIs %s", node_name, results[node_name]['core'])
+
         return results
index 0ab10d7..8e6a3a3 100644 (file)
@@ -23,8 +23,7 @@ from itertools import chain, repeat
 
 import six
 from six.moves.configparser import ConfigParser
-
-from yardstick.common.utils import ip_to_hex
+from yardstick.common import utils
 
 LOG = logging.getLogger(__name__)
 
@@ -34,19 +33,6 @@ link {0} config {1} {2}
 link {0} up
 """
 
-ACTION_TEMPLATE = """\
-p action add {0} accept
-p action add {0} fwd {0}
-p action add {0} count
-"""
-
-FW_ACTION_TEMPLATE = """\
-p action add {0} accept
-p action add {0} fwd {0}
-p action add {0} count
-p action add {0} conntrack
-"""
-
 # This sets up a basic passthrough with no rules
 SCRIPT_TPL = """
 {link_config}
@@ -59,9 +45,7 @@ SCRIPT_TPL = """
 
 {arp_route_tbl6}
 
-{actions}
-
-{rules}
+{flows}
 
 """
 
@@ -182,26 +166,9 @@ class MultiPortConfig(object):
             return parser.get(section, key)
         return default
 
-    @staticmethod
-    def make_ip_addr(ip, mask):
-        """
-        :param ip: ip adddress
-        :type ip: str
-        :param mask: /24 prefix of 255.255.255.0 netmask
-        :type mask: str
-        :return: interface
-        :rtype: IPv4Interface
-        """
-
-        try:
-            return ipaddress.ip_interface(six.text_type('/'.join([ip, mask])))
-        except (TypeError, ValueError):
-            # None so we can skip later
-            return None
-
     @classmethod
     def validate_ip_and_prefixlen(cls, ip_addr, prefixlen):
-        ip_addr = cls.make_ip_addr(ip_addr, prefixlen)
+        ip_addr = utils.make_ip_addr(ip_addr, prefixlen)
         return ip_addr.ip.exploded, ip_addr.network.prefixlen
 
     def __init__(self, topology_file, config_tpl, tmp_file, vnfd_helper,
@@ -245,7 +212,7 @@ class MultiPortConfig(object):
         self.ports_len = 0
         self.prv_que_handler = None
         self.vnfd = None
-        self.rules = None
+        self.flows = None
         self.pktq_out = []
 
     @staticmethod
@@ -360,7 +327,7 @@ class MultiPortConfig(object):
                 "%s/%s" % (interface["dst_ip"], interface["netmask"])))
 
             arp_vars = {
-                "port_netmask_hex": ip_to_hex(dst_port_ip.network.netmask.exploded),
+                "port_netmask_hex": utils.ip_to_hex(dst_port_ip.network.netmask.exploded),
                 # this is the port num that contains port0 subnet and next_hop_ip_hex
                 # this is LINKID which should be based on DPDK port number
                 "port_num": dpdk_port_num,
@@ -542,7 +509,7 @@ class MultiPortConfig(object):
                 self.update_write_parser(self.loadb_tpl)
                 self.start_core += 1
 
-            for i in range(self.worker_threads):
+            for _ in range(self.worker_threads):
                 vnf_data = self.generate_vnf_data()
                 if not self.vnf_tpl:
                     self.vnf_tpl = {}
@@ -637,65 +604,8 @@ class MultiPortConfig(object):
 
         return '\n'.join(('p {3} arpadd {0} {1} {2}'.format(*values) for values in arp_config6))
 
-    def generate_action_config(self):
-        port_list = (self.vnfd_helper.port_num(p) for p in self.all_ports)
-        if self.vnf_type == "VFW":
-            template = FW_ACTION_TEMPLATE
-        else:
-            template = ACTION_TEMPLATE
-
-        return ''.join((template.format(port) for port in port_list))
-
-    def get_ip_from_port(self, port):
-        # we can't use gateway because in OpenStack gateways interfer with floating ip routing
-        # return self.make_ip_addr(self.get_ports_gateway(port), self.get_netmask_gateway(port))
-        vintf = self.vnfd_helper.find_interface(name=port)["virtual-interface"]
-        ip = vintf["local_ip"]
-        netmask = vintf["netmask"]
-        return self.make_ip_addr(ip, netmask)
-
-    def get_network_and_prefixlen_from_ip_of_port(self, port):
-        ip_addr = self.get_ip_from_port(port)
-        # handle cases with no gateway
-        if ip_addr:
-            return ip_addr.network.network_address.exploded, ip_addr.network.prefixlen
-        else:
-            return None, None
-
-    def generate_rule_config(self):
-        cmd = 'acl' if self.vnf_type == "ACL" else "vfw"
-        rules_config = self.rules if self.rules else ''
-        new_rules = []
-        new_ipv6_rules = []
-        pattern = 'p {0} add {1} {2} {3} {4} {5} 0 65535 0 65535 0 0 {6}'
-        for src_intf, dst_intf in self.port_pair_list:
-            src_port = self.vnfd_helper.port_num(src_intf)
-            dst_port = self.vnfd_helper.port_num(dst_intf)
-
-            src_net, src_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(src_intf)
-            dst_net, dst_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(dst_intf)
-            # ignore entires with empty values
-            if all((src_net, src_prefix_len, dst_net, dst_prefix_len)):
-                new_rules.append((cmd, self.txrx_pipeline, src_net, src_prefix_len,
-                                  dst_net, dst_prefix_len, dst_port))
-                new_rules.append((cmd, self.txrx_pipeline, dst_net, dst_prefix_len,
-                                  src_net, src_prefix_len, src_port))
-
-            # src_net = self.get_ports_gateway6(port_pair[0])
-            # src_prefix_len = self.get_netmask_gateway6(port_pair[0])
-            # dst_net = self.get_ports_gateway6(port_pair[1])
-            # dst_prefix_len = self.get_netmask_gateway6(port_pair[0])
-            # # ignore entires with empty values
-            # if all((src_net, src_prefix_len, dst_net, dst_prefix_len)):
-            #     new_ipv6_rules.append((cmd, self.txrx_pipeline, src_net, src_prefix_len,
-            #                            dst_net, dst_prefix_len, dst_port))
-            #     new_ipv6_rules.append((cmd, self.txrx_pipeline, dst_net, dst_prefix_len,
-            #                            src_net, src_prefix_len, src_port))
-
-        acl_apply = "\np %s applyruleset" % cmd
-        new_rules_config = '\n'.join(pattern.format(*values) for values
-                                     in chain(new_rules, new_ipv6_rules))
-        return ''.join([rules_config, new_rules_config, acl_apply])
+    def get_flows_config(self):
+        return self.flows if self.flows else ''
 
     def generate_script_data(self):
         self._port_pairs = PortPairs(self.vnfd_helper.interfaces)
@@ -707,24 +617,15 @@ class MultiPortConfig(object):
             # disable IPv6 for now
             # 'arp_config6': self.generate_arp_config6(),
             'arp_config6': "",
-            'arp_config': self.generate_arp_config(),
             'arp_route_tbl': self.generate_arp_route_tbl(),
             'arp_route_tbl6': "",
-            'actions': '',
-            'rules': '',
+            'flows': self.get_flows_config()
         }
-
-        if self.vnf_type in ('ACL', 'VFW'):
-            script_data.update({
-                'actions': self.generate_action_config(),
-                'rules': self.generate_rule_config(),
-            })
-
         return script_data
 
-    def generate_script(self, vnfd, rules=None):
+    def generate_script(self, vnfd, flows=None):
         self.vnfd = vnfd
-        self.rules = rules
+        self.flows = flows
         script_data = self.generate_script_data()
         script = SCRIPT_TPL.format(**script_data)
         if self.lb_config == self.HW_LB:
index 393f60f..74deeec 100644 (file)
@@ -166,9 +166,10 @@ class IxNextgen(object):  # pragma: no cover
         :return: list of paired frame sizes and weights
         """
         weighted_range_pairs = []
-        for size, weight in framesize.items():
-            weighted_range_pairs.append(int(size.upper().replace('B', '')))
-            weighted_range_pairs.append(int(weight))
+        for size, weight in ((s, w) for (s, w) in framesize.items()
+                             if int(w) != 0):
+            size = int(size.upper().replace('B', ''))
+            weighted_range_pairs.append([size, size, int(weight)])
         return weighted_range_pairs
 
     def iter_over_get_lists(self, x1, x2, y2, offset=0):
@@ -339,7 +340,7 @@ class IxNextgen(object):  # pragma: no cover
                         "percentLineRate" no used)
         - Frame size: custom IMIX [1] definition; a list of packet size in
                       bytes and the weight. E.g.:
-                      [64, 10, 128, 15, 512, 5]
+                      [[64, 64, 10], [128, 128, 15], [512, 512, 5]]
 
         [1] https://en.wikipedia.org/wiki/Internet_Mix
 
index 0c0bf22..5922bd3 100644 (file)
@@ -31,6 +31,7 @@ from yardstick.common.exceptions import ResourceCommandError
 from yardstick.common.task_template import finalize_for_yaml
 from yardstick.common.utils import validate_non_string_sequence
 from yardstick.network_services.nfvi.collectd import AmqpConsumer
+from yardstick.benchmark.contexts import heat
 
 
 LOG = logging.getLogger(__name__)
@@ -52,7 +53,8 @@ class ResourceProfile(object):
     DEFAULT_TIMEOUT = 3600
     OVS_SOCKET_PATH = "/usr/local/var/run/openvswitch/db.sock"
 
-    def __init__(self, mgmt, port_names=None, plugins=None, interval=None, timeout=None):
+    def __init__(self, mgmt, port_names=None, plugins=None,
+                 interval=None, timeout=None, reset_mq_flag=True):
 
         if plugins is None:
             self.plugins = {}
@@ -77,6 +79,7 @@ class ResourceProfile(object):
         # we need to save mgmt so we can connect to port 5672
         self.mgmt = mgmt
         self.connection = ssh.AutoConnectSSH.from_node(mgmt)
+        self._reset_mq_flag = reset_mq_flag
 
     @classmethod
     def make_from_node(cls, node, timeout):
@@ -87,7 +90,10 @@ class ResourceProfile(object):
         plugins = collectd_options.get("plugins", {})
         interval = collectd_options.get("interval")
 
-        return cls(node, plugins=plugins, interval=interval, timeout=timeout)
+        reset_mq_flag = (False if node.get("ctx_type") == heat.HeatContext.__context_type__
+                          else True)
+        return cls(node, plugins=plugins, interval=interval,
+                   timeout=timeout, reset_mq_flag=reset_mq_flag)
 
     def check_if_system_agent_running(self, process):
         """ verify if system agent is running """
@@ -210,11 +216,14 @@ class ResourceProfile(object):
         if not self.enable:
             return {}
 
+        if self.check_if_system_agent_running("collectd")[0] != 0:
+            return {}
+
         metric = {}
         while not self._queue.empty():
             metric.update(self._queue.get())
-        msg = self.parse_collectd_result(metric)
-        return msg
+
+        return self.parse_collectd_result(metric)
 
     def _provide_config_file(self, config_file_path, nfvi_cfg, template_kwargs):
         template = pkg_resources.resource_string("yardstick.network_services.nfvi",
@@ -250,7 +259,7 @@ class ResourceProfile(object):
         if status != 0:
             LOG.error("cannot find OVS socket %s", socket_path)
 
-    def _start_rabbitmq(self, connection):
+    def _reset_rabbitmq(self, connection):
         # Reset amqp queue
         LOG.debug("reset and setup amqp to collect data from collectd")
         # ensure collectd.conf.d exists to avoid error/warning
@@ -263,10 +272,37 @@ class ResourceProfile(object):
                     "sudo rabbitmqctl authenticate_user admin admin",
                     "sudo rabbitmqctl set_permissions -p / admin '.*' '.*' '.*'"
                     ]
+
         for cmd in cmd_list:
-                exit_status, stdout, stderr = connection.execute(cmd)
-                if exit_status != 0:
-                    raise ResourceCommandError(command=cmd, stderr=stderr)
+            exit_status, _, stderr = connection.execute(cmd)
+            if exit_status != 0:
+                raise ResourceCommandError(command=cmd, stderr=stderr)
+
+    def _check_rabbitmq_user(self, connection, user='admin'):
+        exit_status, stdout, _ = connection.execute("sudo rabbitmqctl list_users")
+        if exit_status == 0:
+            for line in stdout.split('\n')[1:]:
+                if line.split('\t')[0] == user:
+                    return True
+
+    def _set_rabbitmq_admin_user(self, connection):
+        LOG.debug("add admin user to amqp")
+        cmd_list = ["sudo rabbitmqctl add_user admin admin",
+                    "sudo rabbitmqctl authenticate_user admin admin",
+                    "sudo rabbitmqctl set_permissions -p / admin '.*' '.*' '.*'"
+                    ]
+
+        for cmd in cmd_list:
+            exit_status, stdout, stderr = connection.execute(cmd)
+            if exit_status != 0:
+                raise ResourceCommandError(command=cmd, stdout=stdout, stderr=stderr)
+
+    def _start_rabbitmq(self, connection):
+        if self._reset_mq_flag:
+            self._reset_rabbitmq(connection)
+        else:
+            if not self._check_rabbitmq_user(connection):
+                self._set_rabbitmq_admin_user(connection)
 
         # check stdout for "sudo rabbitmqctl status" command
         cmd = "sudo rabbitmqctl status"
@@ -282,10 +318,11 @@ class ResourceProfile(object):
         self._prepare_collectd_conf(config_file_path)
 
         connection.execute('sudo pkill -x -9 collectd')
-        exit_status = connection.execute("which %s > /dev/null 2>&1" % collectd_path)[0]
+        cmd = "which %s > /dev/null 2>&1" % collectd_path
+        exit_status, _, stderr = connection.execute(cmd)
         if exit_status != 0:
-            LOG.warning("%s is not present disabling", collectd_path)
-            return
+            raise ResourceCommandError(command=cmd, stderr=stderr)
+
         if "ovs_stats" in self.plugins:
             self._setup_ovs_stats(connection)
 
@@ -293,8 +330,12 @@ class ResourceProfile(object):
         LOG.debug("Start collectd service..... %s second timeout", self.timeout)
         # intel_pmu plug requires large numbers of files open, so try to set
         # ulimit -n to a large value
-        connection.execute("sudo bash -c 'ulimit -n 1000000 ; %s'" % collectd_path,
-                           timeout=self.timeout)
+
+        cmd = "sudo bash -c 'ulimit -n 1000000 ; %s'" % collectd_path
+        exit_status, _, stderr = connection.execute(cmd, timeout=self.timeout)
+        if exit_status != 0:
+            raise ResourceCommandError(command=cmd, stderr=stderr)
+
         LOG.debug("Done")
 
     def initiate_systemagent(self, bin_path):
@@ -334,5 +375,7 @@ class ResourceProfile(object):
         if pid:
             self.connection.execute('sudo kill -9 "%s"' % pid)
         self.connection.execute('sudo pkill -9 "%s"' % agent)
-        self.connection.execute('sudo service rabbitmq-server stop')
-        self.connection.execute("sudo rabbitmqctl stop_app")
+
+        if self._reset_mq_flag:
+            self.connection.execute('sudo service rabbitmq-server stop')
+            self.connection.execute("sudo rabbitmqctl stop_app")
index 9eba550..f4b5b17 100644 (file)
@@ -16,6 +16,31 @@ from yardstick.common import exceptions
 from yardstick.common import utils
 
 
+class TrafficProfileConfig(object):
+    """Class to contain the TrafficProfile class information
+
+    This object will parse and validate the traffic profile information.
+    """
+
+    DEFAULT_SCHEMA = 'nsb:traffic_profile:0.1'
+    DEFAULT_FRAME_RATE = 100
+    DEFAULT_DURATION = 30
+
+    def __init__(self, tp_config):
+        self.schema = tp_config.get('schema', self.DEFAULT_SCHEMA)
+        self.name = tp_config.get('name')
+        self.description = tp_config.get('description')
+        tprofile = tp_config['traffic_profile']
+        self.traffic_type = tprofile.get('traffic_type')
+        self.frame_rate = tprofile.get('frame_rate', self.DEFAULT_FRAME_RATE)
+        self.test_precision = tprofile.get('test_precision')
+        self.packet_sizes = tprofile.get('packet_sizes')
+        self.duration = tprofile.get('duration', self.DEFAULT_DURATION)
+        self.lower_bound = tprofile.get('lower_bound')
+        self.upper_bound = tprofile.get('upper_bound')
+        self.step_interval = tprofile.get('step_interval')
+
+
 class TrafficProfile(object):
     """
     This class defines the behavior
@@ -43,6 +68,7 @@ class TrafficProfile(object):
         # e.g. RFC2544 start_ip, stop_ip, drop_rate,
         # IMIX = {"10K": 0.1, "100M": 0.5}
         self.params = tp_config
+        self.config = TrafficProfileConfig(tp_config)
 
     def execute_traffic(self, traffic_generator, **kawrgs):
         """ This methods defines the behavior of the traffic generator.
index 73806f9..3933678 100644 (file)
@@ -25,6 +25,10 @@ class IXIARFC2544Profile(TrexProfile):
     UPLINK = 'uplink'
     DOWNLINK = 'downlink'
 
+    def __init__(self, yaml_data):
+        super(IXIARFC2544Profile, self).__init__(yaml_data)
+        self.rate = self.config.frame_rate
+
     def _get_ixia_traffic_profile(self, profile_data, mac=None):
         if mac is None:
             mac = {}
@@ -95,7 +99,6 @@ class IXIARFC2544Profile(TrexProfile):
                 if not profile_data:
                     continue
                 self.profile_data = profile_data
-                self.get_streams(self.profile_data)
                 self.full_profile.update({vld_id: self.profile_data})
                 for intf in intfs:
                     yield traffic_generator.vnfd_helper.port_num(intf)
index 225ee43..9457096 100644 (file)
@@ -21,6 +21,7 @@ import time
 
 from yardstick.network_services.traffic_profile.prox_profile import ProxProfile
 from yardstick.network_services import constants
+from yardstick.common import constants as overall_constants
 
 LOG = logging.getLogger(__name__)
 
@@ -84,9 +85,14 @@ class ProxBinSearchProfile(ProxProfile):
         # success, the binary search will complete on an integer multiple
         # of the precision, rather than on a fraction of it.
 
-        theor_max_thruput = 0
+        theor_max_thruput = actual_max_thruput = 0
 
         result_samples = {}
+        rate_samples = {}
+        pos_retry = 0
+        neg_retry = 0
+        total_retry = 0
+        ok_retry = 0
 
         # Store one time only value in influxdb
         single_samples = {
@@ -102,47 +108,91 @@ class ProxBinSearchProfile(ProxProfile):
         successful_pkt_loss = 0.0
         line_speed = traffic_gen.scenario_helper.all_options.get(
             "interface_speed_gbps", constants.NIC_GBPS_DEFAULT) * constants.ONE_GIGABIT_IN_BITS
-        for test_value in self.bounds_iterator(LOG):
-            result, port_samples = self._profile_helper.run_test(pkt_size, duration,
-                                                                 test_value,
-                                                                 self.tolerated_loss,
-                                                                 line_speed)
-            self.curr_time = time.time()
-            self.prev_time = self.curr_time
-
-            if result.success:
-                LOG.debug("Success! Increasing lower bound")
-                self.current_lower = test_value
-                successful_pkt_loss = result.pkt_loss
-                samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
-
-                # store results with success tag in influxdb
-                success_samples = {'Success_' + key: value for key, value in samples.items()}
-
-                # Store number of packets based statistics (we already have throughput)
-                success_samples["Success_rx_total"] = int(result.rx_total)
-                success_samples["Success_tx_total"] = int(result.tx_total)
-                success_samples["Success_can_be_lost"] = int(result.can_be_lost)
-                success_samples["Success_drop_total"] = int(result.drop_total)
-                self.queue.put(success_samples)
-
-                # Store Actual throughput for result samples
-                result_samples["Result_Actual_throughput"] = \
-                    success_samples["Success_RxThroughput"]
-            else:
-                LOG.debug("Failure... Decreasing upper bound")
-                self.current_upper = test_value
-                samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
-                # samples  contains data such as Latency, Throughput, number of packets
-                # Hence they should not be divided by the time difference
-
-            if theor_max_thruput < samples["RequestedTxThroughput"]:
-                theor_max_thruput = samples['RequestedTxThroughput']
-                self.queue.put({'theor_max_throughput': theor_max_thruput})
-
-            LOG.debug("Collect TG KPIs %s %s", datetime.datetime.now(), samples)
-            self.queue.put(samples)
 
+        ok_retry = traffic_gen.scenario_helper.scenario_cfg["runner"].get("confirmation", 0)
+        for test_value in self.bounds_iterator(LOG):
+            pos_retry = 0
+            neg_retry = 0
+            total_retry = 0
+
+            rate_samples["MAX_Rate"] = self.current_upper
+            rate_samples["MIN_Rate"] = self.current_lower
+            rate_samples["Test_Rate"] = test_value
+            self.queue.put(rate_samples, True, overall_constants.QUEUE_PUT_TIMEOUT)
+            LOG.info("Checking MAX %s MIN %s TEST %s",
+                self.current_upper, self.lower_bound, test_value)
+            while (pos_retry <= ok_retry) and (neg_retry <= ok_retry):
+
+                total_retry = total_retry + 1
+                result, port_samples = self._profile_helper.run_test(pkt_size, duration,
+                                                                     test_value,
+                                                                     self.tolerated_loss,
+                                                                     line_speed)
+                if (total_retry > (ok_retry * 3)) and (ok_retry is not 0):
+                    LOG.info("Failure.!! .. RETRY EXCEEDED ... decrease lower bound")
+
+                    successful_pkt_loss = result.pkt_loss
+                    samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
+
+                    self.current_upper = test_value
+                    neg_retry = total_retry
+                elif result.success:
+                    if (pos_retry < ok_retry) and (ok_retry is not 0):
+                        neg_retry = 0
+                        LOG.info("Success! ... confirm retry")
+
+                        successful_pkt_loss = result.pkt_loss
+                        samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
+
+                    else:
+                        LOG.info("Success! Increasing lower bound")
+                        self.current_lower = test_value
+
+                        successful_pkt_loss = result.pkt_loss
+                        samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
+
+                        # store results with success tag in influxdb
+                        success_samples = \
+                            {'Success_' + key: value for key, value in samples.items()}
+
+                        success_samples["Success_rx_total"] = int(result.rx_total)
+                        success_samples["Success_tx_total"] = int(result.tx_total)
+                        success_samples["Success_can_be_lost"] = int(result.can_be_lost)
+                        success_samples["Success_drop_total"] = int(result.drop_total)
+                        success_samples["Success_RxThroughput"] = samples["RxThroughput"]
+                        success_samples["Success_RxThroughput_gbps"] = \
+                            (samples["RxThroughput"] / 1000) * ((pkt_size + 20)* 8)
+                        LOG.info(">>>##>>Collect SUCCESS TG KPIs %s %s",
+                                 datetime.datetime.now(), success_samples)
+                        self.queue.put(success_samples, True, overall_constants.QUEUE_PUT_TIMEOUT)
+
+                        # Store Actual throughput for result samples
+                        actual_max_thruput = success_samples["Success_RxThroughput"]
+
+                    pos_retry = pos_retry + 1
+
+                else:
+                    if (neg_retry < ok_retry) and (ok_retry is not 0):
+
+                        pos_retry = 0
+                        LOG.info("failure! ... confirm retry")
+                    else:
+                        LOG.info("Failure... Decreasing upper bound")
+                        self.current_upper = test_value
+
+                    neg_retry = neg_retry + 1
+                    samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
+
+                if theor_max_thruput < samples["TxThroughput"]:
+                    theor_max_thruput = samples['TxThroughput']
+                    self.queue.put({'theor_max_throughput': theor_max_thruput})
+
+                LOG.info(">>>##>>Collect TG KPIs %s %s", datetime.datetime.now(), samples)
+                self.queue.put(samples, True, overall_constants.QUEUE_PUT_TIMEOUT)
+
+        LOG.info(">>>##>> Result Reached PktSize %s Theor_Max_Thruput %s Actual_throughput %s",
+                 pkt_size, theor_max_thruput, actual_max_thruput)
         result_samples["Result_pktSize"] = pkt_size
         result_samples["Result_theor_max_throughput"] = theor_max_thruput
+        result_samples["Result_Actual_throughput"] = actual_max_thruput
         self.queue.put(result_samples)
index 83020c8..c24e2f6 100644 (file)
 # 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.
-""" RFC2544 Throughput implemenation """
 
-from __future__ import absolute_import
-from __future__ import division
 import logging
 
-from trex_stl_lib.trex_stl_client import STLStream
-from trex_stl_lib.trex_stl_streams import STLFlowLatencyStats
-from trex_stl_lib.trex_stl_streams import STLTXCont
+from trex_stl_lib import api as Pkt
+from trex_stl_lib import trex_stl_client
+from trex_stl_lib import trex_stl_packet_builder_scapy
+from trex_stl_lib import trex_stl_streams
+
+from yardstick.network_services.traffic_profile import trex_traffic_profile
 
-from yardstick.network_services.traffic_profile.trex_traffic_profile \
-    import TrexProfile
 
 LOGGING = logging.getLogger(__name__)
+SRC_PORT = 'sport'
+DST_PORT = 'dport'
+
+
+class PortPgIDMap(object):
+    """Port and pg_id mapping class
+
+    "pg_id" is the identification STL library gives to each stream. In the
+    RFC2544Profile class, the traffic has a STLProfile per port, which contains
+    one or several streams, one per packet size defined in the IMIX test case
+    description.
+
+    Example of port <-> pg_id map:
+        self._port_pg_id_map = {
+            0: [1, 2, 3, 4],
+            1: [5, 6, 7, 8]
+        }
+    """
+
+    def __init__(self):
+        self._pg_id = 0
+        self._last_port = None
+        self._port_pg_id_map = {}
+
+    def add_port(self, port):
+        self._last_port = port
+        self._port_pg_id_map[port] = []
+
+    def get_pg_ids(self, port):
+        return self._port_pg_id_map.get(port)
+
+    def increase_pg_id(self, port=None):
+        port = self._last_port if not port else port
+        if port is None:
+            return
+        pg_id_list = self._port_pg_id_map.get(port)
+        if not pg_id_list:
+            self.add_port(port)
+            pg_id_list = self._port_pg_id_map[port]
+        self._pg_id += 1
+        pg_id_list.append(self._pg_id)
+        return self._pg_id
 
 
-class RFC2544Profile(TrexProfile):
-    """ This class handles rfc2544 implemenation. """
+class RFC2544Profile(trex_traffic_profile.TrexProfile):
+    """TRex RFC2544 traffic profile"""
+
+    TOLERANCE_LIMIT = 0.05
 
     def __init__(self, traffic_generator):
         super(RFC2544Profile, self).__init__(traffic_generator)
         self.generator = None
-        self.max_rate = None
-        self.min_rate = None
-        self.ports = None
-        self.rate = 100
-        self.drop_percent_at_max_tx = None
-        self.throughput_max = None
+        self.rate = self.config.frame_rate
+        self.max_rate = self.config.frame_rate
+        self.min_rate = 0
+        self.drop_percent_max = 0
 
     def register_generator(self, generator):
         self.generator = generator
 
-    def execute_traffic(self, traffic_generator=None):
-        """ Generate the stream and run traffic on the given ports """
+    def stop_traffic(self, traffic_generator=None):
+        """"Stop traffic injection, reset counters and remove streams"""
         if traffic_generator is not None and self.generator is None:
             self.generator = traffic_generator
 
-        if self.ports is not None:
-            return
+        self.generator.client.stop()
+        self.generator.client.reset()
+        self.generator.client.remove_all_streams()
+
+    def execute_traffic(self, traffic_generator=None):
+        """Generate the stream and run traffic on the given ports
+
+        :param traffic_generator: (TrexTrafficGenRFC) traffic generator
+        :return ports: (list of int) indexes of ports
+                port_pg_id: (dict) port indexes and pg_id [1] map
+        [1] https://trex-tgn.cisco.com/trex/doc/cp_stl_docs/api/
+            profile_code.html#stlstream-modes
+        """
+        if traffic_generator is not None and self.generator is None:
+            self.generator = traffic_generator
 
-        self.ports = []
+        port_pg_id = PortPgIDMap()
+        ports = []
         for vld_id, intfs in sorted(self.generator.networks.items()):
             profile_data = self.params.get(vld_id)
-            # no profile for this port
             if not profile_data:
                 continue
-            # correlated traffic doesn't use public traffic?
-            if vld_id.startswith(self.DOWNLINK) and \
-                self.generator.rfc2544_helper.correlated_traffic:
+            if (vld_id.startswith(self.DOWNLINK) and
+                    self.generator.rfc2544_helper.correlated_traffic):
                 continue
             for intf in intfs:
-                port = self.generator.port_num(intf)
-                self.ports.append(port)
-                self.generator.client.add_streams(self.get_streams(profile_data), ports=port)
-
-        self.max_rate = self.rate
-        self.min_rate = 0
-        self.generator.client.start(ports=self.ports, mult=self.get_multiplier(),
-                                    duration=30, force=True)
-        self.drop_percent_at_max_tx = 0
-        self.throughput_max = 0
-
-    def get_multiplier(self):
-        """ Get the rate at which next iteration to run """
-        self.rate = round((self.max_rate + self.min_rate) / 2.0, 2)
-        multiplier = round(self.rate / self.pps, 2)
-        return str(multiplier)
-
-    def get_drop_percentage(self, generator=None):
-        """ Calculate the drop percentage and run the traffic """
-        if generator is None:
-            generator = self.generator
-        run_duration = self.generator.RUN_DURATION
-        samples = self.generator.generate_samples(self.ports)
-
-        in_packets = sum([value['in_packets'] for value in samples.values()])
-        out_packets = sum([value['out_packets'] for value in samples.values()])
-
-        packet_drop = abs(out_packets - in_packets)
-        drop_percent = 100.0
-        try:
-            drop_percent = round((packet_drop / float(out_packets)) * 100, 5)
-        except ZeroDivisionError:
-            LOGGING.info('No traffic is flowing')
+                port_num = int(self.generator.port_num(intf))
+                ports.append(port_num)
+                port_pg_id.add_port(port_num)
+                profile = self._create_profile(profile_data,
+                                               self.rate, port_pg_id)
+                self.generator.client.add_streams(profile, ports=[port_num])
+
+        self.generator.client.start(ports=ports,
+                                    duration=self.config.duration,
+                                    force=True)
+        return ports, port_pg_id
+
+    def _create_profile(self, profile_data, rate, port_pg_id):
+        """Create a STL profile (list of streams) for a port"""
+        streams = []
+        for packet_name in profile_data:
+            imix = (profile_data[packet_name].
+                    get('outer_l2', {}).get('framesize'))
+            imix_data = self._create_imix_data(imix)
+            self._create_vm(profile_data[packet_name])
+            _streams = self._create_streams(imix_data, rate, port_pg_id)
+            streams.extend(_streams)
+        return trex_stl_streams.STLProfile(streams)
+
+    def _create_imix_data(self, imix):
+        """Generate the IMIX distribution for a STL profile
+
+        The input information is the framesize dictionary in a test case
+        traffic profile definition. E.g.:
+          downlink_0:
+            ipv4:
+              id: 2
+                outer_l2:
+                  framesize:
+                    64B: 10
+                    128B: 20
+                    ...
+
+        This function normalizes the sum of framesize weights to 100 and
+        returns a dictionary of frame sizes in bytes and weight in percentage.
+        E.g.:
+          imix_count = {64: 25, 128: 75}
+
+        :param imix: (dict) IMIX size and weight
+        """
+        imix_count = {}
+        if not imix:
+            return imix_count
+
+        imix_count = {size.upper().replace('B', ''): int(weight)
+                      for size, weight in imix.items()}
+        imix_sum = sum(imix_count.values())
+        if imix_sum <= 0:
+            imix_count = {64: 100}
+            imix_sum = 100
+
+        weight_normalize = float(imix_sum) / 100
+        return {size: float(weight) / weight_normalize
+                for size, weight in imix_count.items()}
+
+    def _create_vm(self, packet_definition):
+        """Create the STL Raw instructions"""
+        self.ether_packet = Pkt.Ether()
+        self.ip_packet = Pkt.IP()
+        self.ip6_packet = None
+        self.udp_packet = Pkt.UDP()
+        self.udp[DST_PORT] = 'UDP.dport'
+        self.udp[SRC_PORT] = 'UDP.sport'
+        self.qinq = False
+        self.vm_flow_vars = []
+        outer_l2 = packet_definition.get('outer_l2')
+        outer_l3v4 = packet_definition.get('outer_l3v4')
+        outer_l3v6 = packet_definition.get('outer_l3v6')
+        outer_l4 = packet_definition.get('outer_l4')
+        if outer_l2:
+            self._set_outer_l2_fields(outer_l2)
+        if outer_l3v4:
+            self._set_outer_l3v4_fields(outer_l3v4)
+        if outer_l3v6:
+            self._set_outer_l3v6_fields(outer_l3v6)
+        if outer_l4:
+            self._set_outer_l4_fields(outer_l4)
+        self.trex_vm = trex_stl_packet_builder_scapy.STLScVmRaw(
+            self.vm_flow_vars)
+
+    def _create_single_packet(self, size=64):
+        size -= 4
+        ether_packet = self.ether_packet
+        ip_packet = self.ip6_packet if self.ip6_packet else self.ip_packet
+        udp_packet = self.udp_packet
+        if self.qinq:
+            qinq_packet = self.qinq_packet
+            base_pkt = ether_packet / qinq_packet / ip_packet / udp_packet
+        else:
+            base_pkt = ether_packet / ip_packet / udp_packet
+        pad = max(0, size - len(base_pkt)) * 'x'
+        return trex_stl_packet_builder_scapy.STLPktBuilder(
+            pkt=base_pkt / pad, vm=self.trex_vm)
+
+    def _create_streams(self, imix_data, rate, port_pg_id):
+        """Create a list of streams per packet size
+
+        The STL TX mode speed of the generated streams will depend on the frame
+        weight and the frame rate. Both the frame weight and the total frame
+        rate are normalized to 100. The STL TX mode speed, defined in
+        percentage, is the combitation of both percentages. E.g.:
+          frame weight = 100
+          rate = 90
+            --> STLTXmode percentage = 10 (%)
+
+          frame weight = 80
+          rate = 50
+            --> STLTXmode percentage = 40 (%)
+
+        :param imix_data: (dict) IMIX size and weight
+        :param rate: (float) normalized [0..100] total weight
+        :param pg_id: (PortPgIDMap) port / pg_id (list) map
+        """
+        streams = []
+        for size, weight in ((int(size), float(weight)) for (size, weight)
+                             in imix_data.items() if float(weight) > 0):
+            packet = self._create_single_packet(size)
+            pg_id = port_pg_id.increase_pg_id()
+            stl_flow = trex_stl_streams.STLFlowLatencyStats(pg_id=pg_id)
+            mode = trex_stl_streams.STLTXCont(percentage=weight * rate / 100)
+            streams.append(trex_stl_client.STLStream(
+                packet=packet, flow_stats=stl_flow, mode=mode))
+        return streams
+
+    def get_drop_percentage(self, samples, tol_low, tol_high,
+                            correlated_traffic):
+        """Calculate the drop percentage and run the traffic"""
+        tx_rate_fps = 0
+        rx_rate_fps = 0
+        for sample in samples:
+            tx_rate_fps += sum(
+                port['tx_throughput_fps'] for port in sample.values())
+            rx_rate_fps += sum(
+                port['rx_throughput_fps'] for port in sample.values())
+        tx_rate_fps = round(float(tx_rate_fps) / len(samples), 2)
+        rx_rate_fps = round(float(rx_rate_fps) / len(samples), 2)
 
         # TODO(esm): RFC2544 doesn't tolerate packet loss, why do we?
-        tolerance_low = generator.rfc2544_helper.tolerance_low
-        tolerance_high = generator.rfc2544_helper.tolerance_high
-
-        tx_rate = out_packets / run_duration
-        rx_rate = in_packets / run_duration
-
-        throughput_max = self.throughput_max
-        drop_percent_at_max_tx = self.drop_percent_at_max_tx
+        out_packets = sum(port['out_packets'] for port in samples[-1].values())
+        in_packets = sum(port['in_packets'] for port in samples[-1].values())
+        drop_percent = 100.0
 
-        if self.drop_percent_at_max_tx is None:
-            self.rate = tx_rate
-            self.first_run = False
+        # https://tools.ietf.org/html/rfc2544#section-26.3
+        if out_packets:
+            drop_percent = round(
+                (float(abs(out_packets - in_packets)) / out_packets) * 100, 5)
 
-        if drop_percent > tolerance_high:
-            # TODO(esm): why don't we discard results that are out of tolerance?
+        tol_high = tol_high if tol_high > self.TOLERANCE_LIMIT else tol_high
+        tol_low = tol_low if tol_low > self.TOLERANCE_LIMIT else tol_low
+        if drop_percent > tol_high:
             self.max_rate = self.rate
-            if throughput_max == 0:
-                throughput_max = rx_rate
-                drop_percent_at_max_tx = drop_percent
-
-        elif drop_percent >= tolerance_low:
-            # TODO(esm): why do we update the samples dict in this case
-            #            and not update our tracking values?
-            throughput_max = rx_rate
-            drop_percent_at_max_tx = drop_percent
-
-        elif drop_percent >= self.drop_percent_at_max_tx:
-            # TODO(esm): why don't we discard results that are out of tolerance?
+        elif drop_percent < tol_low:
             self.min_rate = self.rate
-            self.drop_percent_at_max_tx = drop_percent_at_max_tx = drop_percent
-            self.throughput_max = throughput_max = rx_rate
+        # else:
+            # NOTE(ralonsoh): the test should finish here
+            # pass
+        last_rate = self.rate
+        self.rate = round(float(self.max_rate + self.min_rate) / 2.0, 5)
 
-        else:
-            # TODO(esm): why don't we discard results that are out of tolerance?
-            self.min_rate = self.rate
+        throughput = rx_rate_fps * 2 if correlated_traffic else rx_rate_fps
 
-        generator.clear_client_stats(self.ports)
-        generator.start_client(self.ports, mult=self.get_multiplier(),
-                               duration=run_duration, force=True)
+        if drop_percent > self.drop_percent_max:
+            self.drop_percent_max = drop_percent
 
-        # if correlated traffic update the Throughput
-        if generator.rfc2544_helper.correlated_traffic:
-            throughput_max *= 2
+        latency = {port_num: value['latency']
+                   for port_num, value in samples[-1].items()}
 
-        samples.update({
-            'TxThroughput': tx_rate,
-            'RxThroughput': rx_rate,
+        output = {
+            'TxThroughput': tx_rate_fps,
+            'RxThroughput': rx_rate_fps,
             'CurrentDropPercentage': drop_percent,
-            'Throughput': throughput_max,
-            'DropPercentage': drop_percent_at_max_tx,
-        })
-
-        return samples
-
-    def execute_latency(self, generator=None, samples=None):
-        if generator is not None and self.generator is None:
-            self.generator = generator
-
-        if samples is None:
-            samples = self.generator.generate_samples()
-
-        self.pps, multiplier = self.calculate_pps(samples)
-        self.ports = []
-        self.pg_id = self.params['traffic_profile'].get('pg_id', 1)
-        for vld_id, intfs in sorted(self.generator.networks.items()):
-            profile_data = self.params.get(vld_id)
-            if not profile_data:
-                continue
-            # correlated traffic doesn't use public traffic?
-            if vld_id.startswith(self.DOWNLINK) and \
-                self.generator.rfc2544_helper.correlated_traffic:
-                continue
-            for intf in intfs:
-                port = self.generator.port_num(intf)
-                self.ports.append(port)
-                self.generator.client.add_streams(self.get_streams(profile_data), ports=port)
-
-        self.generator.start_client(ports=self.ports, mult=str(multiplier),
-                                    duration=120, force=True)
-        self.first_run = False
-
-    def calculate_pps(self, samples):
-        pps = round(samples['Throughput'] / 2, 2)
-        multiplier = round(self.rate / self.pps, 2)
-        return pps, multiplier
-
-    def create_single_stream(self, packet_size, pps, isg=0):
-        packet = self._create_single_packet(packet_size)
-        if pps:
-            stl_mode = STLTXCont(pps=pps)
-        else:
-            stl_mode = STLTXCont(pps=self.pps)
-        if self.pg_id:
-            LOGGING.debug("pg_id: %s", self.pg_id)
-            stl_flow_stats = STLFlowLatencyStats(pg_id=self.pg_id)
-            stream = STLStream(isg=isg, packet=packet, mode=stl_mode,
-                               flow_stats=stl_flow_stats)
-            self.pg_id += 1
-        else:
-            stream = STLStream(isg=isg, packet=packet, mode=stl_mode)
-        return stream
+            'Throughput': throughput,
+            'DropPercentage': self.drop_percent_max,
+            'Rate': last_rate,
+            'Latency': latency
+        }
+        return output
index f5e3923..ed0355f 100644 (file)
@@ -19,21 +19,16 @@ from random import SystemRandom
 import ipaddress
 
 import six
-
-from yardstick.common import exceptions as y_exc
-from yardstick.network_services.traffic_profile import base
-from trex_stl_lib.trex_stl_client import STLStream
-from trex_stl_lib.trex_stl_streams import STLFlowLatencyStats
-from trex_stl_lib.trex_stl_streams import STLTXCont
-from trex_stl_lib.trex_stl_streams import STLProfile
 from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmWrFlowVar
 from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmFlowVarRepeatableRandom
 from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmFlowVar
-from trex_stl_lib.trex_stl_packet_builder_scapy import STLPktBuilder
-from trex_stl_lib.trex_stl_packet_builder_scapy import STLScVmRaw
 from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmFixIpv4
 from trex_stl_lib import api as Pkt
 
+from yardstick.common import exceptions as y_exc
+from yardstick.network_services.traffic_profile import base
+
+
 SRC = 'src'
 DST = 'dst'
 ETHERNET = 'Ethernet'
@@ -342,115 +337,6 @@ class TrexProfile(base.TrafficProfile):
         if 'dstport' in outer_l4:
             self._set_proto_addr(UDP, DST_PORT, outer_l4['dstport'], outer_l4['count'])
 
-    def generate_imix_data(self, packet_definition):
-        """ generate packet size for a given traffic profile """
-        imix_count = {}
-        imix_data = {}
-        if not packet_definition:
-            return imix_count
-        imix = packet_definition.get('framesize')
-        if imix:
-            for size in imix:
-                data = imix[size]
-                imix_data[int(size[:-1])] = int(data)
-            imix_sum = sum(imix_data.values())
-            if imix_sum > 100:
-                raise SystemExit("Error in IMIX data")
-            elif imix_sum < 100:
-                imix_data[64] = imix_data.get(64, 0) + (100 - imix_sum)
-
-            avg_size = 0.0
-            for size in imix_data:
-                count = int(imix_data[size])
-                if count:
-                    avg_size += round(size * count / 100, 2)
-                    pps = round(self.pps * count / 100, 0)
-                    imix_count[size] = pps
-            self.rate = round(1342177280 / avg_size, 0) * 2
-            logging.debug("Imax: %s rate: %s", imix_count, self.rate)
-        return imix_count
-
-    def get_streams(self, profile_data):
-        """ generate trex stream
-        :param profile_data:
-        :type profile_data:
-        """
-        self.streams = []
-        self.pps = self.params['traffic_profile'].get('frame_rate', 100)
-        for packet_name in profile_data:
-            outer_l2 = profile_data[packet_name].get('outer_l2')
-            imix_data = self.generate_imix_data(outer_l2)
-            if not imix_data:
-                imix_data = {64: self.pps}
-            self.generate_vm(profile_data[packet_name])
-            for size in imix_data:
-                self._generate_streams(size, imix_data[size])
-        self._generate_profile()
-        return self.profile
-
-    def generate_vm(self, packet_definition):
-        """ generate  trex vm with flows setup """
-        self.ether_packet = Pkt.Ether()
-        self.ip_packet = Pkt.IP()
-        self.ip6_packet = None
-        self.udp_packet = Pkt.UDP()
-        self.udp[DST_PORT] = 'UDP.dport'
-        self.udp[SRC_PORT] = 'UDP.sport'
-        self.qinq = False
-        self.vm_flow_vars = []
-        outer_l2 = packet_definition.get('outer_l2', None)
-        outer_l3v4 = packet_definition.get('outer_l3v4', None)
-        outer_l3v6 = packet_definition.get('outer_l3v6', None)
-        outer_l4 = packet_definition.get('outer_l4', None)
-        if outer_l2:
-            self._set_outer_l2_fields(outer_l2)
-        if outer_l3v4:
-            self._set_outer_l3v4_fields(outer_l3v4)
-        if outer_l3v6:
-            self._set_outer_l3v6_fields(outer_l3v6)
-        if outer_l4:
-            self._set_outer_l4_fields(outer_l4)
-        self.trex_vm = STLScVmRaw(self.vm_flow_vars)
-
-    def generate_packets(self):
-        """ generate packets from trex TG """
-        base_pkt = self.base_pkt
-        size = self.fsize - 4
-        pad = max(0, size - len(base_pkt)) * 'x'
-        self.packets = [STLPktBuilder(pkt=base_pkt / pad,
-                                      vm=vm) for vm in self.vms]
-
-    def _create_single_packet(self, size=64):
-        size = size - 4
-        ether_packet = self.ether_packet
-        ip_packet = self.ip6_packet if self.ip6_packet else self.ip_packet
-        udp_packet = self.udp_packet
-        if self.qinq:
-            qinq_packet = self.qinq_packet
-            base_pkt = ether_packet / qinq_packet / ip_packet / udp_packet
-        else:
-            base_pkt = ether_packet / ip_packet / udp_packet
-        pad = max(0, size - len(base_pkt)) * 'x'
-        packet = STLPktBuilder(pkt=base_pkt / pad, vm=self.trex_vm)
-        return packet
-
-    def _create_single_stream(self, packet_size, pps, isg=0):
-        packet = self._create_single_packet(packet_size)
-        if self.pg_id:
-            self.pg_id += 1
-            stl_flow = STLFlowLatencyStats(pg_id=self.pg_id)
-            stream = STLStream(isg=isg, packet=packet, mode=STLTXCont(pps=pps),
-                               flow_stats=stl_flow)
-        else:
-            stream = STLStream(isg=isg, packet=packet, mode=STLTXCont(pps=pps))
-        return stream
-
-    def _generate_streams(self, packet_size, pps):
-        self.streams.append(self._create_single_stream(packet_size, pps))
-
-    def _generate_profile(self):
-        self.profile = STLProfile(self.streams)
-
     @classmethod
     def _count_ip(cls, start_ip, end_ip):
         start = ipaddress.ip_address(six.u(start_ip))
index d9719eb..1357f6b 100644 (file)
 # limitations under the License.
 
 import logging
-
+import ipaddress
+import six
 from yardstick.common import utils
+from yardstick.common import exceptions
+
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, DpdkVnfSetupEnvHelper
-from yardstick.network_services.yang_model import YangModel
+from yardstick.network_services.helpers.samplevnf_helper import PortPairs
+from itertools import chain
 
 LOG = logging.getLogger(__name__)
 
@@ -38,6 +42,196 @@ class AclApproxSetupEnvSetupEnvHelper(DpdkVnfSetupEnvHelper):
     SW_DEFAULT_CORE = 5
     DEFAULT_CONFIG_TPL_CFG = "acl.cfg"
     VNF_TYPE = "ACL"
+    RULE_CMD = "acl"
+
+    DEFAULT_PRIORITY = 1
+    DEFAULT_PROTOCOL = 0
+    DEFAULT_PROTOCOL_MASK = 0
+    # Default actions to be applied to SampleVNF. Please note,
+    # that this list is extended with `fwd` action when default
+    # actions are generated.
+    DEFAULT_FWD_ACTIONS = ["accept", "count"]
+
+    def __init__(self, vnfd_helper, ssh_helper, scenario_helper):
+        super(AclApproxSetupEnvSetupEnvHelper, self).__init__(vnfd_helper,
+                                                              ssh_helper,
+                                                              scenario_helper)
+        self._action_id = 0
+
+    def get_ip_from_port(self, port):
+        # we can't use gateway because in OpenStack gateways interfere with floating ip routing
+        # return self.make_ip_addr(self.get_ports_gateway(port), self.get_netmask_gateway(port))
+        vintf = self.vnfd_helper.find_interface(name=port)["virtual-interface"]
+        return utils.make_ip_addr(vintf["local_ip"], vintf["netmask"])
+
+    def get_network_and_prefixlen_from_ip_of_port(self, port):
+        ip_addr = self.get_ip_from_port(port)
+        # handle cases with no gateway
+        if ip_addr:
+            return ip_addr.network.network_address.exploded, ip_addr.network.prefixlen
+        else:
+            return None, None
+
+    @property
+    def new_action_id(self):
+        """Get new action id"""
+        self._action_id += 1
+        return self._action_id
+
+    def get_default_flows(self):
+        """Get default actions/rules
+        Returns: (<actions>, <rules>)
+            <actions>:
+                 { <action_id>: [ <list of actions> ]}
+            Example:
+                 { 0 : [ "accept", "count", {"fwd" : "port": 0} ], ... }
+            <rules>:
+                 [ {"src_ip": "x.x.x.x", "src_ip_mask", 24, ...}, ... ]
+            Note:
+                See `generate_rule_cmds()` to get list of possible map keys.
+        """
+        actions, rules = {}, []
+        _port_pairs = PortPairs(self.vnfd_helper.interfaces)
+        port_pair_list = _port_pairs.port_pair_list
+        for src_intf, dst_intf in port_pair_list:
+            # get port numbers of the interfaces
+            src_port = self.vnfd_helper.port_num(src_intf)
+            dst_port = self.vnfd_helper.port_num(dst_intf)
+            # get interface addresses and prefixes
+            src_net, src_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(src_intf)
+            dst_net, dst_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(dst_intf)
+            # ignore entries with empty values
+            if all((src_net, src_prefix_len, dst_net, dst_prefix_len)):
+                # flow: src_net:dst_net -> dst_port
+                action_id = self.new_action_id
+                actions[action_id] = self.DEFAULT_FWD_ACTIONS[:]
+                actions[action_id].append({"fwd": {"port": dst_port}})
+                rules.append({"priority": 1, 'cmd': self.RULE_CMD,
+                    "src_ip": src_net, "src_ip_mask": src_prefix_len,
+                    "dst_ip": dst_net, "dst_ip_mask": dst_prefix_len,
+                    "src_port_from": 0, "src_port_to": 65535,
+                    "dst_port_from": 0, "dst_port_to": 65535,
+                    "protocol": 0, "protocol_mask": 0,
+                    "action_id": action_id})
+                # flow: dst_net:src_net -> src_port
+                action_id = self.new_action_id
+                actions[action_id] = self.DEFAULT_FWD_ACTIONS[:]
+                actions[action_id].append({"fwd": {"port": src_port}})
+                rules.append({"cmd":self.RULE_CMD, "priority": 1,
+                    "src_ip": dst_net, "src_ip_mask": dst_prefix_len,
+                    "dst_ip": src_net, "dst_ip_mask": src_prefix_len,
+                    "src_port_from": 0, "src_port_to": 65535,
+                    "dst_port_from": 0, "dst_port_to": 65535,
+                    "protocol": 0, "protocol_mask": 0,
+                    "action_id": action_id})
+        return actions, rules
+
+    def get_flows(self, options):
+        """Get actions/rules based on provided options.
+        The `options` is a dict representing the ACL rules configuration
+        file. Result is the same as described in `get_default_flows()`.
+        """
+        actions, rules = {}, []
+        for ace in options['access-list-entries']:
+            # Generate list of actions
+            action_id = self.new_action_id
+            actions[action_id] = ace['actions']
+            # Destination nestwork
+            matches = ace['matches']
+            dst_ipv4_net = matches['destination-ipv4-network']
+            dst_ipv4_net_ip = ipaddress.ip_interface(six.text_type(dst_ipv4_net))
+            # Source network
+            src_ipv4_net = matches['source-ipv4-network']
+            src_ipv4_net_ip = ipaddress.ip_interface(six.text_type(src_ipv4_net))
+            # Append the rule
+            rules.append({'action_id': action_id, 'cmd': self.RULE_CMD,
+                'dst_ip': dst_ipv4_net_ip.network.network_address.exploded,
+                'dst_ip_mask': dst_ipv4_net_ip.network.prefixlen,
+                'src_ip': src_ipv4_net_ip.network.network_address.exploded,
+                'src_ip_mask': src_ipv4_net_ip.network.prefixlen,
+                'dst_port_from': matches['destination-port-range']['lower-port'],
+                'dst_port_to': matches['destination-port-range']['upper-port'],
+                'src_port_from': matches['source-port-range']['lower-port'],
+                'src_port_to': matches['source-port-range']['upper-port'],
+                'priority': matches.get('priority', self.DEFAULT_PRIORITY),
+                'protocol': matches.get('protocol', self.DEFAULT_PROTOCOL),
+                'protocol_mask': matches.get('protocol_mask',
+                                              self.DEFAULT_PROTOCOL_MASK)
+            })
+        return actions, rules
+
+    def generate_rule_cmds(self, rules, apply_rules=False):
+        """Convert rules into list of SampleVNF CLI commands"""
+        rule_template = ("p {cmd} add {priority} {src_ip} {src_ip_mask} "
+                         "{dst_ip} {dst_ip_mask} {src_port_from} {src_port_to} "
+                         "{dst_port_from} {dst_port_to} {protocol} "
+                         "{protocol_mask} {action_id}")
+        rule_cmd_list = []
+        for rule in rules:
+            rule_cmd_list.append(rule_template.format(**rule))
+        if apply_rules:
+            # add command to apply all rules at the end
+            rule_cmd_list.append("p {cmd} applyruleset".format(cmd=self.RULE_CMD))
+        return rule_cmd_list
+
+    def generate_action_cmds(self, actions):
+        """Convert actions into list of SampleVNF CLI commands.
+        These method doesn't validate the provided list of actions. Supported
+        list of actions are limited by SampleVNF. Thus, the user should be
+        responsible to specify correct action name(s). Yardstick should take
+        the provided action by user and apply it to SampleVNF.
+        Anyway, some of the actions require addition parameters to be
+        specified. In case of `fwd` & `nat` action used have to specify
+        the port attribute.
+        """
+        _action_template_map = {
+            "fwd": "p action add {action_id} fwd {port}",
+            "nat": "p action add {action_id} nat {port}"
+        }
+        action_cmd_list = []
+        for action_id, actions in actions.items():
+            for action in actions:
+                if isinstance(action, dict):
+                    for action_name in action.keys():
+                        # user provided an action name with addition options
+                        # e.g.: {"fwd": {"port": 0}}
+                        # format action CLI command and add it to the list
+                        if action_name not in _action_template_map.keys():
+                            raise exceptions.AclUknownActionTemplate(
+                                action_name=action_name)
+                        template = _action_template_map[action_name]
+                        try:
+                            action_cmd_list.append(template.format(
+                                action_id=action_id, **action[action_name]))
+                        except KeyError as exp:
+                            raise exceptions.AclMissingActionArguments(
+                                action_name=action_name,
+                                action_param=exp.args[0])
+                else:
+                    # user provided an action name w/o addition options
+                    # e.g.: "accept", "count"
+                    action_cmd_list.append(
+                        "p action add {action_id} {action}".format(
+                        action_id=action_id, action=action))
+        return action_cmd_list
+
+    def get_flows_config(self, options=None):
+        """Get action/rules configuration commands (string) to be
+        applied to SampleVNF to configure ACL rules (flows).
+        """
+        action_cmd_list, rule_cmd_list = [], []
+        if options:
+            # if file name is set, read actions/rules from the file
+            actions, rules = self.get_flows(options)
+            action_cmd_list = self.generate_action_cmds(actions)
+            rule_cmd_list = self.generate_rule_cmds(rules)
+        # default actions/rules
+        dft_actions, dft_rules = self.get_default_flows()
+        dft_action_cmd_list = self.generate_action_cmds(dft_actions)
+        dft_rule_cmd_list = self.generate_rule_cmds(dft_rules, apply_rules=True)
+        # generate multi-line commands to add actions/rules
+        return '\n'.join(chain(action_cmd_list, dft_action_cmd_list,
+                               rule_cmd_list, dft_rule_cmd_list))
 
 
 class AclApproxVnf(SampleVNF):
@@ -57,12 +251,3 @@ class AclApproxVnf(SampleVNF):
             setup_env_helper_type = AclApproxSetupEnvSetupEnvHelper
 
         super(AclApproxVnf, self).__init__(name, vnfd, setup_env_helper_type, resource_helper_type)
-        self.acl_rules = None
-
-    def _start_vnf(self):
-        yang_model_path = utils.find_relative_file(
-            self.scenario_helper.options['rules'],
-            self.scenario_helper.task_path)
-        yang_model = YangModel(yang_model_path)
-        self.acl_rules = yang_model.get_rules()
-        super(AclApproxVnf, self)._start_vnf()
index 9ceac31..fb41a4e 100644 (file)
@@ -18,6 +18,9 @@ import abc
 import logging
 import six
 
+from yardstick.common import messaging
+from yardstick.common.messaging import payloads
+from yardstick.common.messaging import producer
 from yardstick.network_services.helpers.samplevnf_helper import PortPairs
 
 
@@ -138,6 +141,39 @@ class VnfdHelper(dict):
             yield port_name, port_num
 
 
+class TrafficGeneratorProducer(producer.MessagingProducer):
+    """Class implementing the message producer for traffic generators
+
+    This message producer must be instantiated in the process created
+    "run_traffic" process.
+    """
+    def __init__(self, _id):
+        super(TrafficGeneratorProducer, self).__init__(messaging.TOPIC_TG,
+                                                       _id=_id)
+
+    def tg_method_started(self, version=1):
+        """Send a message to inform the traffic generation has started"""
+        self.send_message(
+            messaging.TG_METHOD_STARTED,
+            payloads.TrafficGeneratorPayload(version=version, iteration=0,
+                                             kpi={}))
+
+    def tg_method_finished(self, version=1):
+        """Send a message to inform the traffic generation has finished"""
+        self.send_message(
+            messaging.TG_METHOD_FINISHED,
+            payloads.TrafficGeneratorPayload(version=version, iteration=0,
+                                             kpi={}))
+
+    def tg_method_iteration(self, iteration, version=1, kpi=None):
+        """Send a message, with KPI, once an iteration has finished"""
+        kpi = {} if kpi is None else kpi
+        self.send_message(
+            messaging.TG_METHOD_ITERATION,
+            payloads.TrafficGeneratorPayload(version=version,
+                                             iteration=iteration, kpi=kpi))
+
+
 @six.add_metaclass(abc.ABCMeta)
 class GenericVNF(object):
     """Class providing file-like API for generic VNF implementation
@@ -216,6 +252,7 @@ class GenericTrafficGen(GenericVNF):
         super(GenericTrafficGen, self).__init__(name, vnfd)
         self.runs_traffic = True
         self.traffic_finished = False
+        self._mq_producer = None
 
     @abc.abstractmethod
     def run_traffic(self, traffic_profile):
@@ -286,3 +323,16 @@ class GenericTrafficGen(GenericVNF):
         :return: True/False
         """
         pass
+
+    @staticmethod
+    def _setup_mq_producer(id):
+        """Setup the TG MQ producer to send messages between processes
+
+        :return: (derived class from ``MessagingProducer``) MQ producer object
+        """
+        return TrafficGeneratorProducer(id)
+
+    def get_mq_producer_id(self):
+        """Return the MQ producer ID if initialized"""
+        if self._mq_producer:
+            return self._mq_producer.get_id()
index 7816c6d..3241719 100644 (file)
@@ -325,7 +325,7 @@ class ProxSocketHelper(object):
 
         return ret_str, False
 
-    def get_data(self, pkt_dump_only=False, timeout=1):
+    def get_data(self, pkt_dump_only=False, timeout=0.01):
         """ read data from the socket """
 
         # This method behaves slightly differently depending on whether it is
@@ -398,8 +398,14 @@ class ProxSocketHelper(object):
 
     def stop(self, cores, task=''):
         """ stop specific cores on the remote instance """
-        LOG.debug("Stopping cores %s", cores)
-        self.put_command("stop {} {}\n".format(join_non_strings(',', cores), task))
+
+        tmpcores = []
+        for core in cores:
+            if core not in tmpcores:
+                tmpcores.append(core)
+
+        LOG.debug("Stopping cores %s", tmpcores)
+        self.put_command("stop {} {}\n".format(join_non_strings(',', tmpcores), task))
         time.sleep(3)
 
     def start_all(self):
@@ -409,8 +415,14 @@ class ProxSocketHelper(object):
 
     def start(self, cores):
         """ start specific cores on the remote instance """
-        LOG.debug("Starting cores %s", cores)
-        self.put_command("start {}\n".format(join_non_strings(',', cores)))
+
+        tmpcores = []
+        for core in cores:
+            if core not in tmpcores:
+                tmpcores.append(core)
+
+        LOG.debug("Starting cores %s", tmpcores)
+        self.put_command("start {}\n".format(join_non_strings(',', tmpcores)))
         time.sleep(3)
 
     def reset_stats(self):
@@ -532,6 +544,51 @@ class ProxSocketHelper(object):
             tsc = int(ret[3])
         return rx, tx, drop, tsc
 
+    def multi_port_stats(self, ports):
+        """get counter values from all ports port"""
+
+        ports_str = ""
+        for port in ports:
+            ports_str = ports_str + str(port) + ","
+        ports_str = ports_str[:-1]
+
+        ports_all_data = []
+        tot_result = [0] * len(ports)
+
+        retry_counter = 0
+        port_index = 0
+        while (len(ports) is not len(ports_all_data)) and (retry_counter < 10):
+            self.put_command("multi port stats {}\n".format(ports_str))
+            ports_all_data = self.get_data().split(";")
+
+            if len(ports) is len(ports_all_data):
+                for port_data_str in ports_all_data:
+
+                    try:
+                        tot_result[port_index] = [try_int(s, 0) for s in port_data_str.split(",")]
+                    except (IndexError, TypeError):
+                        LOG.error("Port Index error %d  %s - retrying ", port_index, port_data_str)
+
+                    if (len(tot_result[port_index]) is not 6) or \
+                                    tot_result[port_index][0] is not ports[port_index]:
+                        ports_all_data = []
+                        tot_result = [0] * len(ports)
+                        port_index = 0
+                        time.sleep(0.1)
+                        LOG.error("Corrupted PACKET %s - retrying", port_data_str)
+                        break
+                    else:
+                        port_index = port_index + 1
+            else:
+                LOG.error("Empty / too much data - retry -%s-", ports_all_data)
+                ports_all_data = []
+                tot_result = [0] * len(ports)
+                port_index = 0
+                time.sleep(0.1)
+
+            retry_counter = retry_counter + 1
+        return tot_result
+
     def port_stats(self, ports):
         """get counter values from a specific port"""
         tot_result = [0] * 12
@@ -912,7 +969,7 @@ class ProxResourceHelper(ClientResourceHelper):
             self._test_type = self.setup_helper.find_in_section('global', 'name', None)
         return self._test_type
 
-    def run_traffic(self, traffic_profile):
+    def run_traffic(self, traffic_profile, *args):
         self._queue.cancel_join_thread()
         self.lower = 0.0
         self.upper = 100.0
@@ -1012,7 +1069,11 @@ class ProxDataHelper(object):
     @property
     def totals_and_pps(self):
         if self._totals_and_pps is None:
-            rx_total, tx_total = self.sut.port_stats(range(self.port_count))[6:8]
+            rx_total = tx_total = 0
+            all_ports = self.sut.multi_port_stats(range(self.port_count))
+            for port in all_ports:
+                rx_total = rx_total + port[1]
+                tx_total = tx_total + port[2]
             requested_pps = self.value / 100.0 * self.line_rate_to_pps()
             self._totals_and_pps = rx_total, tx_total, requested_pps
         return self._totals_and_pps
@@ -1032,19 +1093,18 @@ class ProxDataHelper(object):
     @property
     def samples(self):
         samples = {}
+        ports = []
+        port_names = []
         for port_name, port_num in self.vnfd_helper.ports_iter():
-            try:
-                port_rx_total, port_tx_total = self.sut.port_stats([port_num])[6:8]
-                samples[port_name] = {
-                    "in_packets": port_rx_total,
-                    "out_packets": port_tx_total,
-                }
-            except (KeyError, TypeError, NameError, MemoryError, ValueError,
-                    SystemError, BufferError):
-                samples[port_name] = {
-                    "in_packets": 0,
-                    "out_packets": 0,
-                }
+            ports.append(port_num)
+            port_names.append(port_name)
+
+        results = self.sut.multi_port_stats(ports)
+        for result in results:
+            port_num = result[0]
+            samples[port_names[port_num]] = {
+                    "in_packets": result[1],
+                    "out_packets": result[2]}
         return samples
 
     def __enter__(self):
@@ -1166,12 +1226,32 @@ class ProxProfileHelper(object):
 
         return cores
 
+    def pct_10gbps(self, percent, line_speed):
+        """Get rate in percent of 10 Gbps.
+
+        Returns the rate in percent of 10 Gbps.
+        For instance 100.0 = 10 Gbps; 400.0 = 40 Gbps.
+
+        This helper method isrequired when setting interface_speed option in
+        the testcase because NSB/PROX considers 10Gbps as 100% of line rate,
+        this means that the line rate must be expressed as a percentage of
+        10Gbps.
+
+        :param percent: (float) Percent of line rate (100.0 = line rate).
+        :param line_speed: (int) line rate speed, in bits per second.
+
+        :return: (float) Represents the rate in percent of 10Gbps.
+        """
+        return (percent * line_speed / (
+            constants.ONE_GIGABIT_IN_BITS * constants.NIC_GBPS_DEFAULT))
+
     def run_test(self, pkt_size, duration, value, tolerated_loss=0.0,
                  line_speed=(constants.ONE_GIGABIT_IN_BITS * constants.NIC_GBPS_DEFAULT)):
         data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size,
                                      value, tolerated_loss, line_speed)
 
-        with data_helper, self.traffic_context(pkt_size, value):
+        with data_helper, self.traffic_context(pkt_size,
+                                               self.pct_10gbps(value, line_speed)):
             with data_helper.measure_tot_stats():
                 time.sleep(duration)
                 # Getting statistics to calculate PPS at right speed....
@@ -1431,7 +1511,8 @@ class ProxBngProfileHelper(ProxProfileHelper):
         data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size,
                                      value, tolerated_loss, line_speed)
 
-        with data_helper, self.traffic_context(pkt_size, value):
+        with data_helper, self.traffic_context(pkt_size,
+                                               self.pct_10gbps(value, line_speed)):
             with data_helper.measure_tot_stats():
                 time.sleep(duration)
                 # Getting statistics to calculate PPS at right speed....
@@ -1620,7 +1701,8 @@ class ProxVpeProfileHelper(ProxProfileHelper):
         data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size,
                                      value, tolerated_loss, line_speed)
 
-        with data_helper, self.traffic_context(pkt_size, value):
+        with data_helper, self.traffic_context(pkt_size,
+                                               self.pct_10gbps(value, line_speed)):
             with data_helper.measure_tot_stats():
                 time.sleep(duration)
                 # Getting statistics to calculate PPS at right speed....
@@ -1811,7 +1893,8 @@ class ProxlwAFTRProfileHelper(ProxProfileHelper):
         data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size,
                                      value, tolerated_loss, line_speed)
 
-        with data_helper, self.traffic_context(pkt_size, value):
+        with data_helper, self.traffic_context(pkt_size,
+                                               self.pct_10gbps(value, line_speed)):
             with data_helper.measure_tot_stats():
                 time.sleep(duration)
                 # Getting statistics to calculate PPS at right speed....
index 36f1a19..bc810ec 100644 (file)
@@ -21,6 +21,7 @@ from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxDpdkVnfS
 from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxResourceHelper
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
 from yardstick.network_services import constants
+from yardstick.benchmark.contexts import base as context_base
 
 LOG = logging.getLogger(__name__)
 
@@ -68,13 +69,19 @@ class ProxApproxVnf(SampleVNF):
     def collect_kpi(self):
         # we can't get KPIs if the VNF is down
         check_if_process_failed(self._vnf_process, 0.01)
+
+        physical_node = context_base.Context.get_physical_node_from_server(
+            self.scenario_helper.nodes[self.name])
+
+        result = {"physical_node": physical_node}
+
         if self.resource_helper is None:
-            result = {
+            result.update({
                 "packets_in": 0,
                 "packets_dropped": 0,
                 "packets_fwd": 0,
                 "collect_stats": {"core": {}},
-            }
+            })
             return result
 
         if (self.tsc_hz == 0):
@@ -89,28 +96,40 @@ class ProxApproxVnf(SampleVNF):
             raise RuntimeError("Failed ..Invalid no of ports .. "
                                "1, 2 or 4 ports only supported at this time")
 
-        self.port_stats = self.vnf_execute('port_stats', range(port_count))
+        all_port_stats = self.vnf_execute('multi_port_stats', range(port_count))
+        rx_total = tx_total = tsc = 0
         try:
-            rx_total = self.port_stats[6]
-            tx_total = self.port_stats[7]
-            tsc = self.port_stats[10]
-        except IndexError:
-            LOG.debug("port_stats parse fail ")
-            # return empty dict so we don't mess up existing KPIs
+            for single_port_stats in all_port_stats:
+                rx_total = rx_total + single_port_stats[1]
+                tx_total = tx_total + single_port_stats[2]
+                tsc = tsc + single_port_stats[5]
+        except (TypeError, IndexError):
+            LOG.error("Invalid data ...")
             return {}
 
-        result = {
+        tsc = tsc / port_count
+
+        result.update({
             "packets_in": rx_total,
             "packets_dropped": max((tx_total - rx_total), 0),
             "packets_fwd": tx_total,
             # we share ProxResourceHelper with TG, but we want to collect
             # collectd KPIs here and not TG KPIs, so use a different method name
             "collect_stats": self.resource_helper.collect_collectd_kpi(),
-        }
-        curr_packets_in = int(((rx_total - self.prev_packets_in) * self.tsc_hz)
-                                / (tsc - self.prev_tsc) * port_count)
-        curr_packets_fwd = int(((tx_total - self.prev_packets_sent) * self.tsc_hz)
-                                / (tsc - self.prev_tsc) * port_count)
+        })
+        try:
+            curr_packets_in = int(((rx_total - self.prev_packets_in) * self.tsc_hz)
+                                / (tsc - self.prev_tsc))
+        except ZeroDivisionError:
+            LOG.error("Error.... Divide by Zero")
+            curr_packets_in = 0
+
+        try:
+            curr_packets_fwd = int(((tx_total - self.prev_packets_sent) * self.tsc_hz)
+                                / (tsc - self.prev_tsc))
+        except ZeroDivisionError:
+            LOG.error("Error.... Divide by Zero")
+            curr_packets_fwd = 0
 
         result["curr_packets_in"] = curr_packets_in
         result["curr_packets_fwd"] = curr_packets_fwd
index aea27ff..90b7b21 100644 (file)
@@ -47,7 +47,6 @@ class RouterVNF(SampleVNF):
     def instantiate(self, scenario_cfg, context_cfg):
         self.scenario_helper.scenario_cfg = scenario_cfg
         self.context_cfg = context_cfg
-        self.nfvi_context = Context.get_context_from_server(self.scenario_helper.nodes[self.name])
         self.configure_routes(self.name, scenario_cfg, context_cfg)
 
     def wait_for_instantiate(self):
@@ -107,8 +106,11 @@ class RouterVNF(SampleVNF):
         stdout = self.ssh_helper.execute(ip_link_stats)[1]
         link_stats = self.get_stats(stdout)
         # get RX/TX from link_stats and assign to results
+        physical_node = Context.get_physical_node_from_server(
+            self.scenario_helper.nodes[self.name])
 
         result = {
+            "physical_node": physical_node,
             "packets_in": 0,
             "packets_dropped": 0,
             "packets_fwd": 0,
index ef8b3f1..bc65380 100644 (file)
 # 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.
-""" Base class implementation for generic vnf implementation """
 
-from collections import Mapping
 import logging
 from multiprocessing import Queue, Value, Process
-
 import os
 import posixpath
 import re
+import uuid
 import subprocess
 import time
 
@@ -32,6 +30,7 @@ from yardstick.benchmark.contexts.base import Context
 from yardstick.common import exceptions as y_exceptions
 from yardstick.common.process import check_if_process_failed
 from yardstick.common import utils
+from yardstick.common import yaml_loader
 from yardstick.network_services import constants
 from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper, DpdkNode
 from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig
@@ -41,7 +40,7 @@ from yardstick.network_services.vnf_generic.vnf.base import GenericTrafficGen
 from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
 from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper
 from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
-
+from yardstick.benchmark.contexts.node import NodeContext
 
 LOG = logging.getLogger(__name__)
 
@@ -144,6 +143,13 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
             'vnf_type': self.VNF_TYPE,
         }
 
+        # read actions/rules from file
+        acl_options = None
+        acl_file_name = self.scenario_helper.options.get('rules')
+        if acl_file_name:
+            with utils.open_relative_file(acl_file_name, task_path) as infile:
+                acl_options = yaml_loader.yaml_load(infile)
+
         config_tpl_cfg = utils.find_relative_file(self.DEFAULT_CONFIG_TPL_CFG,
                                                   task_path)
         config_basename = posixpath.basename(self.CFG_CONFIG)
@@ -176,12 +182,17 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
             new_config = self._update_packet_type(new_config, traffic_options)
         self.ssh_helper.upload_config_file(config_basename, new_config)
         self.ssh_helper.upload_config_file(script_basename,
-                                           multiport.generate_script(self.vnfd_helper))
+            multiport.generate_script(self.vnfd_helper,
+                                      self.get_flows_config(acl_options)))
 
         LOG.info("Provision and start the %s", self.APP_NAME)
         self._build_pipeline_kwargs()
         return self.PIPELINE_COMMAND.format(**self.pipeline_kwargs)
 
+    def get_flows_config(self, options=None): # pylint: disable=unused-argument
+        """No actions/rules (flows) by default"""
+        return None
+
     def _build_pipeline_kwargs(self):
         tool_path = self.ssh_helper.provision_tool(tool_file=self.APP_NAME)
         # count the number of actual ports in the list of pairs
@@ -309,6 +320,7 @@ class ResourceHelper(object):
         self.resource = None
         self.setup_helper = setup_helper
         self.ssh_helper = setup_helper.ssh_helper
+        self._enable = True
 
     def setup(self):
         self.resource = self.setup_helper.setup_vnf_environment()
@@ -316,22 +328,33 @@ class ResourceHelper(object):
     def generate_cfg(self):
         pass
 
+    def update_from_context(self, context, attr_name):
+        """Disable resource helper in case of baremetal context.
+
+        And update appropriate node collectd options in context
+        """
+        if isinstance(context, NodeContext):
+            self._enable = False
+            context.update_collectd_options_for_node(self.setup_helper.collectd_options,
+                                                     attr_name)
+
     def _collect_resource_kpi(self):
         result = {}
         status = self.resource.check_if_system_agent_running("collectd")[0]
-        if status == 0:
+        if status == 0 and self._enable:
             result = self.resource.amqp_collect_nfvi_kpi()
 
         result = {"core": result}
         return result
 
     def start_collect(self):
-        self.resource.initiate_systemagent(self.ssh_helper.bin_path)
-        self.resource.start()
-        self.resource.amqp_process_for_nfvi_kpi()
+        if self._enable:
+            self.resource.initiate_systemagent(self.ssh_helper.bin_path)
+            self.resource.start()
+            self.resource.amqp_process_for_nfvi_kpi()
 
     def stop_collect(self):
-        if self.resource:
+        if self.resource and self._enable:
             self.resource.stop()
 
     def collect_kpi(self):
@@ -375,48 +398,24 @@ class ClientResourceHelper(ResourceHelper):
             LOG.error('TRex client not connected')
             return {}
 
-    def generate_samples(self, ports, key=None, default=None):
-        # needs to be used ports
-        last_result = self.get_stats(ports)
-        key_value = last_result.get(key, default)
-
-        if not isinstance(last_result, Mapping):  # added for mock unit test
-            self._terminated.value = 1
-            return {}
-
-        samples = {}
-        # recalculate port for interface and see if it matches ports provided
-        for intf in self.vnfd_helper.interfaces:
-            name = intf["name"]
-            port = self.vnfd_helper.port_num(name)
-            if port in ports:
-                xe_value = last_result.get(port, {})
-                samples[name] = {
-                    "rx_throughput_fps": float(xe_value.get("rx_pps", 0.0)),
-                    "tx_throughput_fps": float(xe_value.get("tx_pps", 0.0)),
-                    "rx_throughput_mbps": float(xe_value.get("rx_bps", 0.0)),
-                    "tx_throughput_mbps": float(xe_value.get("tx_bps", 0.0)),
-                    "in_packets": int(xe_value.get("ipackets", 0)),
-                    "out_packets": int(xe_value.get("opackets", 0)),
-                }
-                if key:
-                    samples[name][key] = key_value
-        return samples
+    def _get_samples(self, ports, port_pg_id=False):
+        raise NotImplementedError()
 
     def _run_traffic_once(self, traffic_profile):
         traffic_profile.execute_traffic(self)
         self.client_started.value = 1
         time.sleep(self.RUN_DURATION)
-        samples = self.generate_samples(traffic_profile.ports)
+        samples = self._get_samples(traffic_profile.ports)
         time.sleep(self.QUEUE_WAIT_TIME)
         self._queue.put(samples)
 
-    def run_traffic(self, traffic_profile):
+    def run_traffic(self, traffic_profile, mq_producer):
         # if we don't do this we can hang waiting for the queue to drain
         # have to do this in the subprocess
         self._queue.cancel_join_thread()
         # fixme: fix passing correct trex config file,
         # instead of searching the default path
+        mq_producer.tg_method_started()
         try:
             self._build_ports()
             self.client = self._connect()
@@ -424,8 +423,11 @@ class ClientResourceHelper(ResourceHelper):
             self.client.remove_all_streams(self.all_ports)  # remove all streams
             traffic_profile.register_generator(self)
 
+            iteration_index = 0
             while self._terminated.value == 0:
+                iteration_index += 1
                 self._run_traffic_once(traffic_profile)
+                mq_producer.tg_method_iteration(iteration_index)
 
             self.client.stop(self.all_ports)
             self.client.disconnect()
@@ -436,6 +438,8 @@ class ClientResourceHelper(ResourceHelper):
                 return  # return if trex/tg server is stopped.
             raise
 
+        mq_producer.tg_method_finished()
+
     def terminate(self):
         self._terminated.value = 1  # stop client
 
@@ -646,7 +650,6 @@ class SampleVNF(GenericVNF):
         self.resource_helper = resource_helper_type(self.setup_helper)
 
         self.context_cfg = None
-        self.nfvi_context = None
         self.pipeline_kwargs = {}
         self.uplink_ports = None
         self.downlink_ports = None
@@ -673,8 +676,10 @@ class SampleVNF(GenericVNF):
         self._update_collectd_options(scenario_cfg, context_cfg)
         self.scenario_helper.scenario_cfg = scenario_cfg
         self.context_cfg = context_cfg
-        self.nfvi_context = Context.get_context_from_server(self.scenario_helper.nodes[self.name])
-        # self.nfvi_context = None
+        self.resource_helper.update_from_context(
+            Context.get_context_from_server(self.scenario_helper.nodes[self.name]),
+            self.scenario_helper.nodes[self.name]
+        )
 
         # vnf deploy is unsupported, use ansible playbooks
         if self.scenario_helper.options.get("vnf_deploy", False):
@@ -828,15 +833,18 @@ class SampleVNF(GenericVNF):
         check_if_process_failed(self._vnf_process, 0.01)
         stats = self.get_stats()
         m = re.search(self.COLLECT_KPI, stats, re.MULTILINE)
+        physical_node = Context.get_physical_node_from_server(
+            self.scenario_helper.nodes[self.name])
+
+        result = {"physical_node": physical_node}
         if m:
-            result = {k: int(m.group(v)) for k, v in self.COLLECT_MAP.items()}
+            result.update({k: int(m.group(v)) for k, v in self.COLLECT_MAP.items()})
             result["collect_stats"] = self.resource_helper.collect_kpi()
         else:
-            result = {
-                "packets_in": 0,
-                "packets_fwd": 0,
-                "packets_dropped": 0,
-            }
+            result.update({"packets_in": 0,
+                           "packets_fwd": 0,
+                           "packets_dropped": 0})
+
         LOG.debug("%s collect KPIs %s", self.APP_NAME, result)
         return result
 
@@ -882,6 +890,11 @@ class SampleVNFTrafficGen(GenericTrafficGen):
 
     def instantiate(self, scenario_cfg, context_cfg):
         self.scenario_helper.scenario_cfg = scenario_cfg
+        self.resource_helper.update_from_context(
+            Context.get_context_from_server(self.scenario_helper.nodes[self.name]),
+            self.scenario_helper.nodes[self.name]
+        )
+
         self.resource_helper.setup()
         # must generate_cfg after DPDK bind because we need port number
         self.resource_helper.generate_cfg()
@@ -905,12 +918,13 @@ class SampleVNFTrafficGen(GenericTrafficGen):
                 LOG.info("%s TG Server is up and running.", self.APP_NAME)
                 return self._tg_process.exitcode
 
-    def _traffic_runner(self, traffic_profile):
+    def _traffic_runner(self, traffic_profile, mq_id):
         # always drop connections first thing in new processes
         # so we don't get paramiko errors
         self.ssh_helper.drop_connection()
         LOG.info("Starting %s client...", self.APP_NAME)
-        self.resource_helper.run_traffic(traffic_profile)
+        self._mq_producer = self._setup_mq_producer(mq_id)
+        self.resource_helper.run_traffic(traffic_profile, self._mq_producer)
 
     def run_traffic(self, traffic_profile):
         """ Generate traffic on the wire according to the given params.
@@ -920,10 +934,12 @@ class SampleVNFTrafficGen(GenericTrafficGen):
         :param traffic_profile:
         :return: True/False
         """
-        name = "{}-{}-{}-{}".format(self.name, self.APP_NAME, traffic_profile.__class__.__name__,
+        name = '{}-{}-{}-{}'.format(self.name, self.APP_NAME,
+                                    traffic_profile.__class__.__name__,
                                     os.getpid())
-        self._traffic_process = Process(name=name, target=self._traffic_runner,
-                                        args=(traffic_profile,))
+        self._traffic_process = Process(
+            name=name, target=self._traffic_runner,
+            args=(traffic_profile, uuid.uuid1().int))
         self._traffic_process.start()
         # Wait for traffic process to start
         while self.resource_helper.client_started.value == 0:
@@ -932,13 +948,16 @@ class SampleVNFTrafficGen(GenericTrafficGen):
             if not self._traffic_process.is_alive():
                 break
 
-        return self._traffic_process.is_alive()
-
     def collect_kpi(self):
         # check if the tg processes have exited
+        physical_node = Context.get_physical_node_from_server(
+            self.scenario_helper.nodes[self.name])
+
+        result = {"physical_node": physical_node}
         for proc in (self._tg_process, self._traffic_process):
             check_if_process_failed(proc)
-        result = self.resource_helper.collect_kpi()
+
+        result["collect_stats"] = self.resource_helper.collect_kpi()
         LOG.debug("%s collect KPIs %s", self.APP_NAME, result)
         return result
 
index 02e7803..102c66f 100644 (file)
@@ -20,7 +20,7 @@ import os
 import shutil
 
 from collections import OrderedDict
-from subprocess import call
+import subprocess
 
 from yardstick.common import utils
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
@@ -101,7 +101,7 @@ class IxLoadResourceHelper(ClientResourceHelper):
         LOG.debug(cmd)
 
         if not os.path.ismount(self.RESULTS_MOUNT):
-            call(cmd, shell=True)
+            subprocess.call(cmd, shell=True)
 
         shutil.rmtree(self.RESULTS_MOUNT, ignore_errors=True)
         utils.makedirs(self.RESULTS_MOUNT)
@@ -157,7 +157,7 @@ class IxLoadTrafficGen(SampleVNFTrafficGen):
             args="'%s'" % ixload_config)
 
         LOG.debug(cmd)
-        call(cmd, shell=True)
+        subprocess.call(cmd, shell=True)
 
         with open(self.ssh_helper.join_bin_path("ixLoad_HTTP_Client.csv")) as csv_file:
             lines = csv_file.readlines()[10:]
@@ -172,5 +172,5 @@ class IxLoadTrafficGen(SampleVNFTrafficGen):
         self.resource_helper.data = self.resource_helper.make_aggregates()
 
     def terminate(self):
-        call(["pkill", "-9", "http_ixload.py"])
+        subprocess.call(["pkill", "-9", "http_ixload.py"])
         super(IxLoadTrafficGen, self).terminate()
index a989543..4050dc6 100644 (file)
@@ -71,7 +71,7 @@ class PingResourceHelper(ClientResourceHelper):
         self._queue = Queue()
         self._parser = PingParser(self._queue)
 
-    def run_traffic(self, traffic_profile):
+    def run_traffic(self, traffic_profile, *args):
         # drop the connection in order to force a new one
         self.ssh_helper.drop_connection()
 
index 2010546..875ae93 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os
 import logging
-import sys
 
-from yardstick.common import exceptions
 from yardstick.common import utils
+from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
@@ -27,14 +25,6 @@ LOG = logging.getLogger(__name__)
 
 WAIT_AFTER_CFG_LOAD = 10
 WAIT_FOR_TRAFFIC = 30
-IXIA_LIB = os.path.dirname(os.path.realpath(__file__))
-IXNET_LIB = os.path.join(IXIA_LIB, "../../libs/ixia_libs/IxNet")
-sys.path.append(IXNET_LIB)
-
-try:
-    from IxNet import IxNextgen
-except ImportError:
-    IxNextgen = exceptions.ErrorClass
 
 
 class IxiaRfc2544Helper(Rfc2544ResourceHelper):
@@ -51,7 +41,7 @@ class IxiaResourceHelper(ClientResourceHelper):
         super(IxiaResourceHelper, self).__init__(setup_helper)
         self.scenario_helper = setup_helper.scenario_helper
 
-        self.client = IxNextgen()
+        self.client = ixnet_api.IxNextgen()
 
         if rfc_helper_type is None:
             rfc_helper_type = IxiaRfc2544Helper
@@ -69,10 +59,8 @@ class IxiaResourceHelper(ClientResourceHelper):
 
     def stop_collect(self):
         self._terminated.value = 1
-        if self.client:
-            self.client.ix_stop_traffic()
 
-    def generate_samples(self, ports, key=None, default=None):
+    def generate_samples(self, ports, key=None):
         stats = self.get_stats()
 
         samples = {}
@@ -114,7 +102,7 @@ class IxiaResourceHelper(ClientResourceHelper):
         self.client.assign_ports()
         self.client.create_traffic_model()
 
-    def run_traffic(self, traffic_profile):
+    def run_traffic(self, traffic_profile, *args):
         if self._terminated.value:
             return
 
index 4e9f4bd..07cec67 100644 (file)
 # 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.
-""" Trex traffic generation definitions which implements rfc2544 """
 
-from __future__ import absolute_import
-from __future__ import print_function
-import time
 import logging
-from collections import Mapping
-
-from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexTrafficGen
-from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
-from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexResourceHelper
-
-LOGGING = logging.getLogger(__name__)
+import time
 
+from yardstick.common import utils
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_trex
 
-class TrexRfc2544ResourceHelper(Rfc2544ResourceHelper):
 
-    def is_done(self):
-        return self.latency and self.iteration.value > 10
+LOGGING = logging.getLogger(__name__)
 
 
-class TrexRfcResourceHelper(TrexResourceHelper):
+class TrexRfcResourceHelper(tg_trex.TrexResourceHelper):
 
-    LATENCY_TIME_SLEEP = 120
-    RUN_DURATION = 30
-    WAIT_TIME = 3
+    SAMPLING_PERIOD = 2
+    TRANSIENT_PERIOD = 10
 
-    def __init__(self, setup_helper, rfc_helper_type=None):
+    def __init__(self, setup_helper):
         super(TrexRfcResourceHelper, self).__init__(setup_helper)
-
-        if rfc_helper_type is None:
-            rfc_helper_type = TrexRfc2544ResourceHelper
-
-        self.rfc2544_helper = rfc_helper_type(self.scenario_helper)
+        self.rfc2544_helper = sample_vnf.Rfc2544ResourceHelper(
+            self.scenario_helper)
 
     def _run_traffic_once(self, traffic_profile):
-        if self._terminated.value:
-            return
-
-        traffic_profile.execute_traffic(self)
         self.client_started.value = 1
-        time.sleep(self.RUN_DURATION)
-        self.client.stop(traffic_profile.ports)
-        time.sleep(self.WAIT_TIME)
-        samples = traffic_profile.get_drop_percentage(self)
-        self._queue.put(samples)
-
-        if not self.rfc2544_helper.is_done():
-            return
-
-        self.client.stop(traffic_profile.ports)
-        self.client.reset(ports=traffic_profile.ports)
-        self.client.remove_all_streams(traffic_profile.ports)
-        traffic_profile.execute_traffic_latency(samples=samples)
-        multiplier = traffic_profile.calculate_pps(samples)[1]
-        for _ in range(5):
-            time.sleep(self.LATENCY_TIME_SLEEP)
-            self.client.stop(traffic_profile.ports)
-            time.sleep(self.WAIT_TIME)
-            last_res = self.client.get_stats(traffic_profile.ports)
-            if not isinstance(last_res, Mapping):
-                self._terminated.value = 1
-                continue
-            self.generate_samples(traffic_profile.ports, 'latency', {})
-            self._queue.put(samples)
-            self.client.start(mult=str(multiplier),
-                              ports=traffic_profile.ports,
-                              duration=120, force=True)
+        ports, port_pg_id = traffic_profile.execute_traffic(self)
+
+        samples = []
+        timeout = int(traffic_profile.config.duration) - self.TRANSIENT_PERIOD
+        time.sleep(self.TRANSIENT_PERIOD)
+        for _ in utils.Timer(timeout=timeout):
+            samples.append(self._get_samples(ports, port_pg_id=port_pg_id))
+            time.sleep(self.SAMPLING_PERIOD)
+
+        traffic_profile.stop_traffic(self)
+        output = traffic_profile.get_drop_percentage(
+            samples, self.rfc2544_helper.tolerance_low,
+            self.rfc2544_helper.tolerance_high,
+            self.rfc2544_helper.correlated_traffic)
+        self._queue.put(output)
 
     def start_client(self, ports, mult=None, duration=None, force=True):
         self.client.start(ports=ports, mult=mult, duration=duration, force=force)
@@ -86,12 +57,8 @@ class TrexRfcResourceHelper(TrexResourceHelper):
     def clear_client_stats(self, ports):
         self.client.clear_stats(ports=ports)
 
-    def collect_kpi(self):
-        self.rfc2544_helper.iteration.value += 1
-        return super(TrexRfcResourceHelper, self).collect_kpi()
-
 
-class TrexTrafficGenRFC(TrexTrafficGen):
+class TrexTrafficGenRFC(tg_trex.TrexTrafficGen):
     """
     This class handles mapping traffic profile and generating
     traffic for rfc2544 testcase.
index 0084a12..80b42e2 100644 (file)
@@ -13,7 +13,6 @@
 # limitations under the License.
 """ Trex acts as traffic generation and vnf definitions based on IETS Spec """
 
-from __future__ import absolute_import
 import logging
 import os
 
@@ -25,6 +24,7 @@ from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTraff
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
 
+
 LOG = logging.getLogger(__name__)
 
 
@@ -165,6 +165,30 @@ class TrexResourceHelper(ClientResourceHelper):
         cmd = "sudo fuser -n tcp %s %s -k > /dev/null 2>&1"
         self.ssh_helper.execute(cmd % (self.SYNC_PORT, self.ASYNC_PORT))
 
+    def _get_samples(self, ports, port_pg_id=None):
+        stats = self.get_stats(ports)
+        samples = {}
+        for pname in (intf['name'] for intf in self.vnfd_helper.interfaces):
+            port_num = self.vnfd_helper.port_num(pname)
+            port_stats = stats.get(port_num, {})
+            samples[pname] = {
+                'rx_throughput_fps': float(port_stats.get('rx_pps', 0.0)),
+                'tx_throughput_fps': float(port_stats.get('tx_pps', 0.0)),
+                'rx_throughput_bps': float(port_stats.get('rx_bps', 0.0)),
+                'tx_throughput_bps': float(port_stats.get('tx_bps', 0.0)),
+                'in_packets': int(port_stats.get('ipackets', 0)),
+                'out_packets': int(port_stats.get('opackets', 0)),
+            }
+
+            pg_id_list = port_pg_id.get_pg_ids(port_num)
+            samples[pname]['latency'] = {}
+            for pg_id in pg_id_list:
+                latency_global = stats.get('latency', {})
+                pg_latency = latency_global.get(pg_id, {}).get('latency')
+                samples[pname]['latency'][pg_id] = pg_latency
+
+        return samples
+
 
 class TrexTrafficGen(SampleVNFTrafficGen):
     """
index a57f53b..fa92744 100644 (file)
@@ -19,7 +19,7 @@ from yardstick.common.process import check_if_process_failed
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
-
+from yardstick.benchmark.contexts import base as ctx_base
 
 LOG = logging.getLogger(__name__)
 
@@ -79,9 +79,11 @@ class UdpReplayApproxVnf(SampleVNF):
         ports_mask_hex = hex(sum(2 ** num for num in port_nums))
         # one core extra for master
         cpu_mask_hex = hex(2 ** (number_of_ports + 1) - 1)
+        nfvi_context = ctx_base.Context.get_context_from_server(
+            self.scenario_helper.nodes[self.name])
         hw_csum = ""
         if (not self.scenario_helper.options.get('hw_csum', False) or
-                self.nfvi_context.attrs.get('nfvi_type') not in self.HW_OFFLOADING_NFVI_TYPES):
+                nfvi_context.attrs.get('nfvi_type') not in self.HW_OFFLOADING_NFVI_TYPES):
             hw_csum = '--no-hw-csum'
 
         # tuples of (FLD_PORT, FLD_QUEUE, FLD_LCORE)
@@ -116,7 +118,12 @@ class UdpReplayApproxVnf(SampleVNF):
         stats = self.get_stats()
         stats_words = stats.split()
         split_stats = stats_words[stats_words.index('0'):][:number_of_ports * 5]
+
+        physical_node = ctx_base.Context.get_physical_node_from_server(
+            self.scenario_helper.nodes[self.name])
+
         result = {
+            "physical_node": physical_node,
             "packets_in": get_sum(1),
             "packets_fwd": get_sum(2),
             "packets_dropped": get_sum(3) + get_sum(4),
index 3ba1f91..432f30a 100644 (file)
@@ -14,9 +14,8 @@
 
 import logging
 
-from yardstick.common import utils
-from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, DpdkVnfSetupEnvHelper
-from yardstick.network_services.yang_model import YangModel
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
+from yardstick.network_services.vnf_generic.vnf.acl_vnf import AclApproxSetupEnvSetupEnvHelper
 
 LOG = logging.getLogger(__name__)
 
@@ -27,7 +26,7 @@ FW_COLLECT_KPI = (r"""VFW TOTAL:[^p]+pkts_received"?:\s(\d+),[^p]+pkts_fw_forwar
                   r"""[^p]+pkts_drop_fw"?:\s(\d+),\s""")
 
 
-class FWApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
+class FWApproxSetupEnvHelper(AclApproxSetupEnvSetupEnvHelper):
 
     APP_NAME = "vFW"
     CFG_CONFIG = "/tmp/vfw_config"
@@ -37,6 +36,8 @@ class FWApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
     SW_DEFAULT_CORE = 5
     HW_DEFAULT_CORE = 2
     VNF_TYPE = "VFW"
+    RULE_CMD = "vfw"
+    DEFAULT_FWD_ACTIONS = ["accept", "count", "conntrack"]
 
 
 class FWApproxVnf(SampleVNF):
@@ -56,12 +57,3 @@ class FWApproxVnf(SampleVNF):
             setup_env_helper_type = FWApproxSetupEnvHelper
 
         super(FWApproxVnf, self).__init__(name, vnfd, setup_env_helper_type, resource_helper_type)
-        self.vfw_rules = None
-
-    def _start_vnf(self):
-        yang_model_path = utils.find_relative_file(
-            self.scenario_helper.options['rules'],
-            self.scenario_helper.task_path)
-        yang_model = YangModel(yang_model_path)
-        self.vfw_rules = yang_model.get_rules()
-        super(FWApproxVnf, self)._start_vnf()
index de6fd93..6c5c6c8 100644 (file)
@@ -47,6 +47,7 @@ class VnfSshHelper(AutoConnectSSH):
 
     def upload_config_file(self, prefix, content):
         cfg_file = os.path.join(constants.REMOTE_TMP, prefix)
+        LOG.debug('Config file name: %s', cfg_file)
         LOG.debug(content)
         file_obj = StringIO(content)
         self.put_file_obj(file_obj, cfg_file)
index 9deef5c..57ea2ee 100644 (file)
@@ -28,6 +28,7 @@ from yardstick.common.process import check_if_process_failed
 from yardstick.network_services.helpers.samplevnf_helper import PortPairs
 from yardstick.network_services.pipeline import PipelineRules
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, DpdkVnfSetupEnvHelper
+from yardstick.benchmark.contexts import base as ctx_base
 
 LOG = logging.getLogger(__name__)
 
@@ -238,7 +239,7 @@ class ConfigCreate(object):
 
 class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
 
-    APP_NAME = 'vPE_vnf'
+    APP_NAME = 'vPE'
     CFG_CONFIG = "/tmp/vpe_config"
     CFG_SCRIPT = "/tmp/vpe_script"
     TM_CONFIG = "/tmp/full_tm_profile_10G.cfg"
@@ -285,7 +286,7 @@ class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
 class VpeApproxVnf(SampleVNF):
     """ This class handles vPE VNF model-driver definitions """
 
-    APP_NAME = 'vPE_vnf'
+    APP_NAME = 'vPE'
     APP_WORD = 'vpe'
     COLLECT_KPI = VPE_COLLECT_KPI
     WAIT_TIME = 20
@@ -302,7 +303,11 @@ class VpeApproxVnf(SampleVNF):
     def collect_kpi(self):
         # we can't get KPIs if the VNF is down
         check_if_process_failed(self._vnf_process)
+        physical_node = ctx_base.Context.get_physical_node_from_server(
+            self.scenario_helper.nodes[self.name])
+
         result = {
+            "physical_node": physical_node,
             'pkt_in_up_stream': 0,
             'pkt_drop_up_stream': 0,
             'pkt_in_down_stream': 0,
diff --git a/yardstick/network_services/yang_model.py b/yardstick/network_services/yang_model.py
deleted file mode 100644 (file)
index ec00c45..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright (c) 2017 Intel Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import absolute_import
-from __future__ import print_function
-import logging
-import ipaddress
-import six
-
-from yardstick.common.yaml_loader import yaml_load
-
-LOG = logging.getLogger(__name__)
-
-
-class YangModel(object):
-
-    RULE_TEMPLATE = "p acl add 1 {0} {1} {2} {3} {4} {5} {6} {7} 0 0 {8}"
-
-    def __init__(self, config_file):
-        super(YangModel, self).__init__()
-        self._config_file = config_file
-        self._options = {}
-        self._rules = ''
-
-    @property
-    def config_file(self):
-        return self._config_file
-
-    @config_file.setter
-    def config_file(self, value):
-        self._config_file = value
-        self._options = {}
-        self._rules = ''
-
-    def _read_config(self):
-        # TODO: add some error handling in case of empty or non-existing file
-        try:
-            with open(self._config_file) as f:
-                self._options = yaml_load(f)
-        except Exception as e:
-            LOG.exception("Failed to load the yaml %s", e)
-            raise
-
-    def _get_entries(self):
-        if not self._options:
-            return ''
-
-        rule_list = []
-        for ace in self._options['access-list1']['acl']['access-list-entries']:
-            # TODO: resolve ports using topology file and nodes'
-            # ids: public or private.
-            matches = ace['ace']['matches']
-            dst_ipv4_net = matches['destination-ipv4-network']
-            dst_ipv4_net_ip = ipaddress.ip_interface(six.text_type(dst_ipv4_net))
-            port0_local_network = dst_ipv4_net_ip.network.network_address.exploded
-            port0_prefix = dst_ipv4_net_ip.network.prefixlen
-
-            src_ipv4_net = matches['source-ipv4-network']
-            src_ipv4_net_ip = ipaddress.ip_interface(six.text_type(src_ipv4_net))
-            port1_local_network = src_ipv4_net_ip.network.network_address.exploded
-            port1_prefix = src_ipv4_net_ip.network.prefixlen
-
-            lower_dport = matches['destination-port-range']['lower-port']
-            upper_dport = matches['destination-port-range']['upper-port']
-
-            lower_sport = matches['source-port-range']['lower-port']
-            upper_sport = matches['source-port-range']['upper-port']
-
-            # TODO: proto should be read from file also.
-            # Now all rules in sample ACL file are TCP.
-            rule_list.append('')  # get an extra new line
-            rule_list.append(self.RULE_TEMPLATE.format(port0_local_network,
-                                                       port0_prefix,
-                                                       port1_local_network,
-                                                       port1_prefix,
-                                                       lower_dport,
-                                                       upper_dport,
-                                                       lower_sport,
-                                                       upper_sport,
-                                                       0))
-            rule_list.append(self.RULE_TEMPLATE.format(port1_local_network,
-                                                       port1_prefix,
-                                                       port0_local_network,
-                                                       port0_prefix,
-                                                       lower_sport,
-                                                       upper_sport,
-                                                       lower_dport,
-                                                       upper_dport,
-                                                       1))
-
-        self._rules = '\n'.join(rule_list)
-
-    def get_rules(self):
-        if not self._rules:
-            self._read_config()
-            self._get_entries()
-        return self._rules
index a595de8..f690ab3 100644 (file)
@@ -31,6 +31,7 @@ class ContainerObject(object):
         self._args = kwargs.get('args', [])
         self._volume_mounts = kwargs.get('volumeMounts', [])
         self._security_context = kwargs.get('securityContext')
+        self._env = kwargs.get('env', [])
 
     def _create_volume_mounts(self):
         """Return all "volumeMounts" items per container"""
@@ -58,6 +59,11 @@ class ContainerObject(object):
                      'volumeMounts': self._create_volume_mounts()}
         if self._security_context:
             container['securityContext'] = self._security_context
+        if self._env:
+            container['env'] = []
+            for env in self._env:
+                container['env'].append({'name': env['name'],
+                                         'value': env['value']})
         return container
 
 
index 6b5e6fa..e6a26ab 100644 (file)
@@ -348,12 +348,14 @@ class SSH(object):
             raise exceptions.SSHError(error_msg=details)
         return exit_status
 
-    def execute(self, cmd, stdin=None, timeout=3600):
+    def execute(self, cmd, stdin=None, timeout=3600, raise_on_error=False):
         """Execute the specified command on the server.
 
-        :param cmd:     Command to be executed.
-        :param stdin:   Open file to be sent on process stdin.
-        :param timeout: Timeout for execution of the command.
+        :param cmd: (str)             Command to be executed.
+        :param stdin: (StringIO)      Open file to be sent on process stdin.
+        :param timeout: (int)         Timeout for execution of the command.
+        :param raise_on_error: (bool) If True, then an SSHError will be raised
+                                      when non-zero exit code.
 
         :returns: tuple (exit_status, stdout, stderr)
         """
@@ -362,7 +364,7 @@ class SSH(object):
 
         exit_status = self.run(cmd, stderr=stderr,
                                stdout=stdout, stdin=stdin,
-                               timeout=timeout, raise_on_error=False)
+                               timeout=timeout, raise_on_error=raise_on_error)
         stdout.seek(0)
         stderr.seek(0)
         return exit_status, stdout.read(), stderr.read()
index 9987434..f3e31e7 100644 (file)
@@ -32,25 +32,25 @@ class DummyPayload(payloads.Payload):
 class DummyEndpoint(consumer.NotificationHandler):
 
     def info(self, ctxt, **kwargs):
-        if ctxt['pid'] in self._ctx_pids:
-            self._queue.put('ID {}, data: {}, pid: {}'.format(
-                self._id, kwargs['data'], ctxt['pid']))
+        if ctxt['id'] in self._ctx_ids:
+            self._queue.put('Nr {}, data: {}, id: {}'.format(
+                self._id, kwargs['data'], ctxt['id']))
 
 
 class DummyConsumer(consumer.MessagingConsumer):
 
-    def __init__(self, _id, ctx_pids, queue):
+    def __init__(self, _id, ctx_ids, queue):
         self._id = _id
-        endpoints = [DummyEndpoint(_id, ctx_pids, queue)]
-        super(DummyConsumer, self).__init__(TOPIC, ctx_pids, endpoints)
+        endpoints = [DummyEndpoint(_id, ctx_ids, queue)]
+        super(DummyConsumer, self).__init__(TOPIC, ctx_ids, endpoints)
 
 
 class DummyProducer(producer.MessagingProducer):
     pass
 
 
-def _run_consumer(_id, ctx_pids, queue):
-    _consumer = DummyConsumer(_id, ctx_pids, queue)
+def _run_consumer(_id, ctx_ids, queue):
+    _consumer = DummyConsumer(_id, ctx_ids, queue)
     _consumer.start_rpc_server()
     _consumer.wait()
 
@@ -67,8 +67,8 @@ class MessagingTestCase(base.BaseFunctionalTestCase):
         num_consumers = 10
         ctx_1 = 100001
         ctx_2 = 100002
-        producers = [DummyProducer(TOPIC, pid=ctx_1),
-                     DummyProducer(TOPIC, pid=ctx_2)]
+        producers = [DummyProducer(TOPIC, _id=ctx_1),
+                     DummyProducer(TOPIC, _id=ctx_2)]
 
         processes = []
         for i in range(num_consumers):
@@ -91,7 +91,7 @@ class MessagingTestCase(base.BaseFunctionalTestCase):
             output.append(output_queue.get(True, 1))
 
         self.assertEqual(num_consumers * 4, len(output))
-        msg_template = 'ID {}, data: {}, pid: {}'
+        msg_template = 'Nr {}, data: {}, id: {}'
         for i in range(num_consumers):
             for ctx in [ctx_1, ctx_2]:
                 for message in ['message 0', 'message 1']:
index 95105d8..6021d35 100644 (file)
@@ -31,15 +31,17 @@ class GetDataDbClientTestCase(base.BaseUnitTestCase):
         _mock_parser.read.assert_called_once_with(constants.CONF_FILE)
         mock_get_client.assert_called_once_with(_mock_parser)
 
+    @mock.patch.object(influx.logger, 'error')
     @mock.patch.object(influx, '_get_influxdb_client',
                        return_value='fake_client')
     @mock.patch.object(influx.ConfigParser, 'ConfigParser')
-    def test_get_data_db_client_parsing_error(self, mock_parser,
-                                              mock_get_client):
+    def test_get_data_db_client_parsing_error(
+            self, mock_parser, mock_get_client, *args):
         _mock_parser = mock.Mock()
         mock_parser.return_value = _mock_parser
         mock_parser.NoOptionError = configparser.NoOptionError
-        mock_get_client.side_effect = configparser.NoOptionError('option', 'section')
+        mock_get_client.side_effect = configparser.NoOptionError('option',
+                                                                 'section')
         with self.assertRaises(configparser.NoOptionError):
             influx.get_data_db_client()
 
index 2cf1d92..8ad5819 100644 (file)
@@ -371,11 +371,6 @@ class StandaloneContextHelperTestCase(unittest.TestCase):
         file_path = os.path.join(curr_path, filename)
         return file_path
 
-    def test_read_config_file(self):
-        self.helper.file_path = self._get_file_abspath(self.NODE_SAMPLE)
-        status = self.helper.read_config_file()
-        self.assertIsNotNone(status)
-
     def test_parse_pod_file(self):
         self.helper.file_path = self._get_file_abspath("dummy")
         self.assertRaises(IOError, self.helper.parse_pod_file,
@@ -549,5 +544,5 @@ class OvsDeployTestCase(unittest.TestCase):
                     'ovs_version': ovs_version,
                     'dpdk_version': dpdk_version,
                     'proxy': 'test_proxy'})
-            mock_execute.assert_called_with(cmd)
-            mock_env_get.assert_called_with('http_proxy', '')
+            mock_execute.assert_called_once_with(cmd)
+            mock_env_get.assert_has_calls([mock.call('http_proxy', '')])
index 6eb438c..a4a8359 100644 (file)
@@ -58,7 +58,10 @@ class OvsDpdkContextTestCase(unittest.TestCase):
             'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
         }
         self.ovs_dpdk = ovs_dpdk.OvsDpdkContext()
+        self._mock_log = mock.patch.object(ovs_dpdk, 'LOG')
+        self.mock_log = self._mock_log.start()
         self.addCleanup(self._remove_contexts)
+        self.addCleanup(self._stop_mocks)
 
     @staticmethod
     def _remove_contexts():
@@ -66,6 +69,9 @@ class OvsDpdkContextTestCase(unittest.TestCase):
             context._delete_context()
         base.Context.list = []
 
+    def _stop_mocks(self):
+        self._mock_log.stop()
+
     @mock.patch('yardstick.benchmark.contexts.standalone.model.Server')
     @mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper')
     def test___init__(self, mock_helper, mock_server):
@@ -290,6 +296,22 @@ class OvsDpdkContextTestCase(unittest.TestCase):
         self.assertEqual(result['user'], 'root')
         self.assertEqual(result['key_filename'], '/root/.yardstick_key')
 
+    def test__get_physical_node_for_server(self):
+        attrs = self.attrs
+        attrs.update({'servers': {'server1': {}}})
+        self.ovs_dpdk.init(attrs)
+
+        # When server is not from this context
+        result = self.ovs_dpdk._get_physical_node_for_server('server1.another-context')
+        self.assertIsNone(result)
+
+        # When node_name is not from this context
+        result = self.ovs_dpdk._get_physical_node_for_server('fake.foo-12345678')
+        self.assertIsNone(result)
+
+        result = self.ovs_dpdk._get_physical_node_for_server('server1.foo-12345678')
+        self.assertEqual(result, 'node5.foo')
+
     # TODO(elfoley): Split this test for networks that exist and networks that
     #                don't
     def test__get_network(self):
index de748e2..1690846 100644 (file)
@@ -62,7 +62,7 @@ class SriovContextTestCase(unittest.TestCase):
         self.attrs = {
             'name': 'foo',
             'task_id': '1234567890',
-            'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE)
+            'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE),
         }
         self.sriov = sriov.SriovContext()
         self.addCleanup(self._remove_contexts)
@@ -171,6 +171,22 @@ class SriovContextTestCase(unittest.TestCase):
         self.assertEqual(result['user'], 'root')
         self.assertEqual(result['key_filename'], '/root/.yardstick_key')
 
+    def test__get_physical_node_for_server(self):
+        attrs = self.attrs
+        attrs.update({'servers': {'server1': {}}})
+        self.sriov.init(attrs)
+
+        # When server is not from this context
+        result = self.sriov._get_physical_node_for_server('server1.another-context')
+        self.assertIsNone(result)
+
+        # When node_name is not from this context
+        result = self.sriov._get_physical_node_for_server('fake.foo-12345678')
+        self.assertIsNone(result)
+
+        result = self.sriov._get_physical_node_for_server('server1.foo-12345678')
+        self.assertEqual(result, 'node5.foo')
+
     def test__get_server_no_task_id(self):
         self.attrs['flags'] = {'no_setup': True}
         self.sriov.init(self.attrs)
index b198834..5fd7352 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import unittest
+import os
+import errno
+
+import mock
 
 from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts.base import Context
+from yardstick.common import yaml_loader
+from yardstick.tests.unit import base as ut_base
+from yardstick.common.constants import YARDSTICK_ROOT_PATH
+
+
+class DummyContextClass(Context):
+
+    __context_type__ = "Dummy"
+
+    def __init__(self, host_name_separator='.'):
+        super(DummyContextClass, self).__init__\
+            (host_name_separator=host_name_separator)
+        self.nodes = []
+        self.controllers = []
+        self.computes = []
+        self.baremetals = []
+
+    def _get_network(self, *args):
+        pass
+
+    def _get_server(self, *args):
+        pass
+
+    def deploy(self):
+        pass
 
+    def undeploy(self):
+        pass
 
-class FlagsTestCase(unittest.TestCase):
+    def _get_physical_nodes(self):
+        pass
+
+    def _get_physical_node_for_server(self, server_name):
+        pass
+
+
+class FlagsTestCase(ut_base.BaseUnitTestCase):
 
     def setUp(self):
         self.flags = base.Flags()
@@ -44,3 +82,93 @@ class FlagsTestCase(unittest.TestCase):
         self.flags.parse(foo=42)
         with self.assertRaises(AttributeError):
             _ = self.flags.foo
+
+
+class ContextTestCase(ut_base.BaseUnitTestCase):
+
+    @staticmethod
+    def _remove_ctx(ctx_obj):
+        if ctx_obj in base.Context.list:
+            base.Context.list.remove(ctx_obj)
+
+    def test_split_host_name(self):
+        ctx_obj = DummyContextClass()
+        self.addCleanup(self._remove_ctx, ctx_obj)
+        config_name = 'host_name.ctx_name'
+        self.assertEqual(('host_name', 'ctx_name'),
+                         ctx_obj.split_host_name(config_name))
+
+    def test_split_host_name_wrong_separator(self):
+        ctx_obj = DummyContextClass()
+        self.addCleanup(self._remove_ctx, ctx_obj)
+        config_name = 'host_name-ctx_name'
+        self.assertEqual((None, None),
+                         ctx_obj.split_host_name(config_name))
+
+    def test_split_host_name_other_separator(self):
+        ctx_obj = DummyContextClass(host_name_separator='-')
+        self.addCleanup(self._remove_ctx, ctx_obj)
+        config_name = 'host_name-ctx_name'
+        self.assertEqual(('host_name', 'ctx_name'),
+                         ctx_obj.split_host_name(config_name))
+
+    def test_get_physical_nodes(self):
+        ctx_obj = DummyContextClass()
+        self.addCleanup(self._remove_ctx, ctx_obj)
+
+        result = Context.get_physical_nodes()
+
+        self.assertEqual(result, {None: None})
+
+    @mock.patch.object(Context, 'get_context_from_server')
+    def test_get_physical_node_from_server(self, mock_get_ctx):
+        ctx_obj = DummyContextClass()
+        self.addCleanup(self._remove_ctx, ctx_obj)
+
+        mock_get_ctx.return_value = ctx_obj
+
+        result = Context.get_physical_node_from_server("mock_server")
+
+        mock_get_ctx.assert_called_once()
+        self.assertIsNone(result)
+
+    @mock.patch.object(yaml_loader, 'read_yaml_file')
+    def test_read_pod_file(self, mock_read_yaml_file):
+        attrs = {'name': 'foo',
+                 'task_id': '12345678',
+                 'file': 'pod.yaml'
+                 }
+
+        ctx_obj = DummyContextClass()
+        cfg = {"nodes": [
+                    {
+                        "name": "node1",
+                        "role": "Controller",
+                        "ip": "10.229.47.137",
+                        "user": "root",
+                        "key_filename": "/root/.yardstick_key"
+                    },
+                    {
+                        "name": "node2",
+                        "role": "Compute",
+                        "ip": "10.229.47.139",
+                        "user": "root",
+                        "key_filename": "/root/.yardstick_key"
+                    }
+                ]
+            }
+
+        mock_read_yaml_file.return_value = cfg
+        result = ctx_obj.read_pod_file(attrs)
+        self.assertEqual(result, cfg)
+
+        mock_read_yaml_file.side_effect = IOError(errno.EPERM, '')
+        with self.assertRaises(IOError):
+            ctx_obj.read_pod_file(attrs)
+
+        mock_read_yaml_file.side_effect = IOError(errno.ENOENT, '')
+        with self.assertRaises(IOError):
+            ctx_obj.read_pod_file(attrs)
+
+        file_path = os.path.join(YARDSTICK_ROOT_PATH, 'pod.yaml')
+        self.assertEqual(ctx_obj.file_path, file_path)
index c4113be..3383237 100644 (file)
@@ -76,3 +76,11 @@ class DummyContextTestCase(unittest.TestCase):
         self.assertEqual(result, None)
 
         self.test_context.undeploy()
+
+    def test__get_physical_nodes(self):
+        result = self.test_context._get_physical_nodes()
+        self.assertIsNone(result)
+
+    def test__get_physical_node_for_server(self):
+        result = self.test_context._get_physical_node_for_server("fake")
+        self.assertIsNone(result)
index 9c822b3..7782d96 100644 (file)
@@ -12,30 +12,54 @@ import logging
 import os
 
 import mock
+import unittest
 
-from yardstick import ssh
 from yardstick.benchmark.contexts import base
 from yardstick.benchmark.contexts import heat
 from yardstick.benchmark.contexts import model
 from yardstick.common import constants as consts
 from yardstick.common import exceptions as y_exc
-from yardstick.tests.unit import base as ut_base
+from yardstick.common import openstack_utils
+from yardstick.common import yaml_loader
+from yardstick import ssh
 
 
 LOG = logging.getLogger(__name__)
 
 
-class HeatContextTestCase(ut_base.BaseUnitTestCase):
+class HeatContextTestCase(unittest.TestCase):
+
+    HEAT_POD_SAMPLE = {
+        "nodes": [
+            {
+                "name": "node1",
+                "role": "Controller",
+                "ip": "10.229.47.137",
+                "user": "root",
+                "key_filename": "/root/.yardstick_key"
+            },
+            {
+                "name": "node2",
+                "role": "Compute",
+                "ip": "10.229.47.139",
+                "user": "root",
+                "key_filename": "/root/.yardstick_key"
+            }
+        ]
+    }
+
+    def __init__(self, *args, **kwargs):
+
+        super(HeatContextTestCase, self).__init__(*args, **kwargs)
 
     def setUp(self):
         self.test_context = heat.HeatContext()
         self.addCleanup(self._remove_contexts)
+        self.mock_context = mock.Mock(spec=heat.HeatContext())
 
-    @staticmethod
-    def _remove_contexts():
-        for context in base.Context.list:
-            context._delete_context()
-        base.Context.list = []
+    def _remove_contexts(self):
+        if self.test_context in self.test_context.list:
+            self.test_context._delete_context()
 
     def test___init__(self):
         self.assertIsNone(self.test_context._name)
@@ -57,24 +81,30 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
         self.assertIsNone(self.test_context.heat_parameters)
         self.assertIsNone(self.test_context.key_filename)
 
+    @mock.patch.object(yaml_loader, 'read_yaml_file')
     @mock.patch('yardstick.benchmark.contexts.heat.PlacementGroup')
     @mock.patch('yardstick.benchmark.contexts.heat.ServerGroup')
     @mock.patch('yardstick.benchmark.contexts.heat.Network')
     @mock.patch('yardstick.benchmark.contexts.heat.Server')
-    def test_init(self, mock_server, mock_network, mock_sg, mock_pg):
+    def test_init(self, mock_server, mock_network, mock_sg, mock_pg,
+                  mock_read_yaml):
 
+        mock_read_yaml.return_value = self.HEAT_POD_SAMPLE
         pgs = {'pgrp1': {'policy': 'availability'}}
         sgs = {'servergroup1': {'policy': 'affinity'}}
         networks = {'bar': {'cidr': '10.0.1.0/24'}}
         servers = {'baz': {'floating_ip': True, 'placement': 'pgrp1'}}
         attrs = {'name': 'foo',
+                 'file': 'pod.yaml',
                  'task_id': '1234567890',
                  'placement_groups': pgs,
                  'server_groups': sgs,
                  'networks': networks,
                  'servers': servers}
 
-        self.test_context.init(attrs)
+        with mock.patch.object(openstack_utils, 'get_shade_client'), \
+             mock.patch.object(openstack_utils, 'get_shade_operator_client'):
+            self.test_context.init(attrs)
 
         self.assertFalse(self.test_context._flags.no_setup)
         self.assertFalse(self.test_context._flags.no_teardown)
@@ -128,13 +158,17 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
                  'server_groups': {},
                  'networks': {},
                  'servers': {},
+                 'file': "pod.yaml",
                  'flags': {
                      'no_setup': True,
                      'no_teardown': True,
                      },
                 }
 
-        self.test_context.init(attrs)
+        with mock.patch.object(openstack_utils, 'get_shade_client'), \
+             mock.patch.object(openstack_utils, 'get_shade_operator_client'):
+            self.test_context.init(attrs)
+
         self.assertTrue(self.test_context._flags.no_setup)
         self.assertTrue(self.test_context._flags.no_teardown)
 
@@ -654,7 +688,6 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
         baz3_server.public_ip = None
         baz3_server.context.user = 'zab'
 
-        self.mock_context = mock.Mock(spec=heat.HeatContext())
         self.mock_context._name = 'bar1'
         self.test_context.stack = mock.Mock()
         self.mock_context.stack.outputs = {
@@ -722,3 +755,56 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
         }
         result = self.test_context._get_network(attr_name)
         self.assertDictEqual(result, expected)
+
+    def _get_file_abspath(self, filename):
+        curr_path = os.path.dirname(os.path.abspath(__file__))
+        file_path = os.path.join(curr_path, filename)
+        return file_path
+
+    def test__get_physical_nodes(self):
+        self.test_context.nodes = {}
+        nodes = self.test_context._get_physical_nodes()
+        self.assertEquals(nodes, {})
+
+    @mock.patch.object(yaml_loader, 'read_yaml_file')
+    def test__get_physical_node_for_server(self, mock_read_yaml):
+        attrs = {'name': 'foo',
+                 'task_id': '12345678',
+                 'file': "pod.yaml",
+                 'servers': {'vnf': {}},
+                 'networks': {'mgmt': {'cidr': '10.0.1.0/24'}}
+                 }
+
+        with mock.patch.object(openstack_utils, 'get_shade_client'), \
+             mock.patch.object(openstack_utils, 'get_shade_operator_client'):
+            mock_read_yaml.return_value = self.HEAT_POD_SAMPLE
+            self.test_context.init(attrs)
+
+        with mock.patch('yardstick.common.openstack_utils.get_server') as mock_get_server:
+            mock_get_server.return_value = {'vnf': {}}
+
+            # When server is not from this context
+            result = self.test_context._get_physical_node_for_server('node1.foo-context')
+            self.assertIsNone(result)
+
+            # When node_name is not from this context
+            result = self.test_context._get_physical_node_for_server('fake.foo-12345678')
+            self.assertIsNone(result)
+
+            mock_munch = mock.Mock()
+            mock_munch.toDict = mock.Mock(return_value={
+                'OS-EXT-SRV-ATTR:hypervisor_hostname': 'hypervisor_hostname'
+            })
+            mock_get_server.return_value = mock_munch
+
+            hypervisor = mock.Mock()
+            hypervisor.hypervisor_hostname = 'hypervisor_hostname'
+            hypervisor.host_ip = '10.229.47.137'
+
+            self.test_context.operator_client.list_hypervisors = mock.Mock(
+                return_value=[hypervisor])
+
+            mock_get_server.return_value = mock_munch
+
+            result = self.test_context._get_physical_node_for_server('vnf.foo-12345678')
+            self.assertEqual(result, 'node1.foo')
index fd7b4f2..3957aab 100644 (file)
@@ -182,3 +182,11 @@ class KubernetesTestCase(unittest.TestCase):
         mock_k8stemplate.assert_called_once_with(self.k8s_context.name,
                                                  CONTEXT_CFG)
         self.assertEqual('fake_template', self.k8s_context.template)
+
+    def test__get_physical_nodes(self):
+        result = self.k8s_context._get_physical_nodes()
+        self.assertIsNone(result)
+
+    def test__get_physical_node_for_server(self):
+        result = self.k8s_context._get_physical_node_for_server("fake")
+        self.assertIsNone(result)
index b67be37..da16074 100644 (file)
@@ -8,13 +8,16 @@
 ##############################################################################
 
 import os
-import unittest
 import errno
+
 import mock
+import unittest
 
-from yardstick.common import constants as consts
 from yardstick.benchmark.contexts import base
 from yardstick.benchmark.contexts import node
+from yardstick.common import constants as consts
+from yardstick.common import exceptions
+from yardstick.common import yaml_loader
 
 
 class NodeContextTestCase(unittest.TestCase):
@@ -55,8 +58,9 @@ class NodeContextTestCase(unittest.TestCase):
         self.assertEqual(self.test_context.env, {})
         self.assertEqual(self.test_context.attrs, {})
 
+    @mock.patch.object(yaml_loader, 'read_yaml_file')
     @mock.patch('{}.os.path.join'.format(PREFIX))
-    def test_init_negative(self, mock_path_join):
+    def test_init_negative(self, mock_path_join, read_mock):
         special_path = '/foo/bar/error_file'
         error_path = self._get_file_abspath("error_file")
 
@@ -68,7 +72,6 @@ class NodeContextTestCase(unittest.TestCase):
         # we can't count mock_path_join calls because
         # it can catch join calls for .pyc files.
         mock_path_join.side_effect = path_join
-        self.test_context.read_config_file = read_mock = mock.Mock()
         read_calls = 0
 
         with self.assertRaises(KeyError):
@@ -86,7 +89,7 @@ class NodeContextTestCase(unittest.TestCase):
             self.test_context.init(attrs)
 
         read_calls += 1
-        self.assertEqual(read_mock.called, read_calls)
+        self.assertEqual(read_mock.call_count, read_calls)
         self.assertIn(attrs['file'], self.test_context.file_path)
         self.assertEqual(raised.exception.errno, errno.EBUSY)
         self.assertEqual(str(raised.exception), str(read_mock.side_effect))
@@ -101,11 +104,6 @@ class NodeContextTestCase(unittest.TestCase):
         self.assertEqual(raised.exception.errno, errno.ENOENT)
         self.assertEqual(str(raised.exception), str(read_mock.side_effect))
 
-    def test_read_config_file(self):
-        self.test_context.init(self.attrs)
-
-        self.assertIsNotNone(self.test_context.read_config_file())
-
     def test__dispatch_script(self):
         self.test_context.init(self.attrs)
 
@@ -171,6 +169,39 @@ class NodeContextTestCase(unittest.TestCase):
         self.assertEqual(result['user'], 'root')
         self.assertEqual(result['key_filename'], '/root/.yardstick_key')
 
+    def test__get_physical_nodes(self):
+        self.test_context.init(self.attrs)
+        nodes = self.test_context._get_physical_nodes()
+        self.assertEqual(nodes, self.test_context.nodes)
+
+    def test__get_physical_node_for_server(self):
+        self.test_context.init(self.attrs)
+
+        # When server is not from this context
+        result = self.test_context._get_physical_node_for_server('node1.another-context')
+        self.assertIsNone(result)
+
+        # When node_name is not from this context
+        result = self.test_context._get_physical_node_for_server('fake.foo-12345678')
+        self.assertIsNone(result)
+
+        result = self.test_context._get_physical_node_for_server('node1.foo-12345678')
+        self.assertEqual(result, 'node1.foo')
+
+    def test_update_collectd_options_for_node(self):
+        self.test_context.init(self.attrs)
+        options = {'collectd': {'interval': 5}}
+
+        with self.assertRaises(exceptions.ContextUpdateCollectdForNodeError):
+            self.test_context.update_collectd_options_for_node(options, 'fake.foo-12345678')
+
+        self.test_context.update_collectd_options_for_node(options, 'node1.foo-12345678')
+
+        node_collectd_options = [node for node in self.test_context.nodes
+                                 if node['name'] == 'node1'][0]['collectd']
+
+        self.assertEqual(node_collectd_options, options)
+
     @mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
     def test_deploy(self, dispatch_script_mock):
         obj = node.NodeContext()
index 0d14e4e..5362131 100644 (file)
@@ -12,6 +12,7 @@ import os
 import pkg_resources
 
 import mock
+import six
 import testtools
 
 from yardstick import ssh
@@ -48,13 +49,17 @@ deployment:
         self.mock_ssh_from_node.return_value = self.mock_ssh_obj
         self.mock_ssh_obj.wait = mock.Mock()
         self.mock_ssh_obj._put_file_shell = mock.Mock()
+        self._mock_log_info = mock.patch.object(plugin.LOG, 'info')
+        self.mock_log_info = self._mock_log_info.start()
 
         self.addCleanup(self._cleanup)
 
     def _cleanup(self):
         self._mock_ssh_from_node.stop()
+        self._mock_log_info.stop()
 
-    def test_install(self):
+    @mock.patch.object(six.moves.builtins, 'print')
+    def test_install(self, *args):
         args = mock.Mock()
         args.input_file = [mock.Mock()]
         with mock.patch.object(self.plugin, '_install_setup') as \
@@ -65,7 +70,8 @@ deployment:
                                                  PluginTestCase.DEPLOYMENT)
             mock_run.assert_called_once_with(PluginTestCase.NAME)
 
-    def test_remove(self):
+    @mock.patch.object(six.moves.builtins, 'print')
+    def test_remove(self, *args):
         args = mock.Mock()
         args.input_file = [mock.Mock()]
         with mock.patch.object(self.plugin, '_remove_setup') as \
index a684ad7..524302f 100644 (file)
@@ -42,16 +42,16 @@ class ReportTestCase(unittest.TestCase):
         self.param.task_id = [FAKE_TASK_ID]
         self.rep = report.Report()
 
-    @mock.patch('yardstick.benchmark.core.report.Report._get_tasks')
-    @mock.patch('yardstick.benchmark.core.report.Report._get_fieldkeys')
-    @mock.patch('yardstick.benchmark.core.report.Report._validate')
+    @mock.patch.object(report.Report, '_get_tasks')
+    @mock.patch.object(report.Report, '_get_fieldkeys')
+    @mock.patch.object(report.Report, '_validate')
     def test_generate_success(self, mock_valid, mock_keys, mock_tasks):
         mock_tasks.return_value = FAKE_DB_TASK
         mock_keys.return_value = FAKE_DB_FIELDKEYS
         self.rep.generate(self.param)
         mock_valid.assert_called_once_with(FAKE_YAML_NAME, FAKE_TASK_ID)
-        self.assertEqual(1, mock_tasks.call_count)
-        self.assertEqual(1, mock_keys.call_count)
+        mock_tasks.assert_called_once_with()
+        mock_keys.assert_called_once_with()
 
     # pylint: disable=deprecated-method
     def test_invalid_yaml_name(self):
index 7468368..0424c77 100644 (file)
@@ -156,6 +156,31 @@ class TaskTestCase(unittest.TestCase):
         t._run([scenario], False, "yardstick.out")
         runner.run.assert_called_once()
 
+    @mock.patch.object(task, 'Context')
+    @mock.patch.object(task, 'base_runner')
+    def test_run_ProxDuration(self, mock_base_runner, *args):
+        scenario = {
+            'host': 'athena.demo',
+            'target': 'ares.demo',
+            'runner': {
+                'duration': 60,
+                'interval': 1,
+                'sampled': 'yes',
+                'confirmation': 1,
+                'type': 'ProxDuration'
+            },
+            'type': 'Ping'
+        }
+
+        t = task.Task()
+        runner = mock.Mock()
+        runner.join.return_value = 0
+        runner.get_output.return_value = {}
+        runner.get_result.return_value = []
+        mock_base_runner.Runner.get.return_value = runner
+        t._run([scenario], False, "yardstick.out")
+        runner.run.assert_called_once()
+
     @mock.patch.object(os, 'environ')
     def test_check_precondition(self, mock_os_environ):
         cfg = {
index 727207f..49ba1ef 100644 (file)
@@ -8,38 +8,47 @@
 ##############################################################################
 
 import time
+import uuid
 
 import mock
-import unittest
-from subprocess import CalledProcessError
+from oslo_config import cfg
+import oslo_messaging
+import subprocess
 
-
-from yardstick.benchmark.runners import base
+from yardstick.benchmark.runners import base as runner_base
 from yardstick.benchmark.runners import iteration
+from yardstick.common import messaging
+from yardstick.common.messaging import payloads
+from yardstick.tests.unit import base as ut_base
 
 
-class ActionTestCase(unittest.TestCase):
+class ActionTestCase(ut_base.BaseUnitTestCase):
 
-    @mock.patch("yardstick.benchmark.runners.base.subprocess")
-    def test__execute_shell_command(self, mock_subprocess):
-        mock_subprocess.check_output.side_effect = CalledProcessError(-1, '')
+    def setUp(self):
+        self._mock_log = mock.patch.object(runner_base.log, 'error')
+        self.mock_log = self._mock_log.start()
+        self.addCleanup(self._stop_mocks)
 
-        self.assertEqual(base._execute_shell_command("")[0], -1)
+    def _stop_mocks(self):
+        self._mock_log.stop()
 
-    @mock.patch("yardstick.benchmark.runners.base.subprocess")
-    def test__single_action(self, mock_subprocess):
-        mock_subprocess.check_output.side_effect = CalledProcessError(-1, '')
+    @mock.patch.object(subprocess, 'check_output')
+    def test__execute_shell_command(self, mock_subprocess):
+        mock_subprocess.side_effect = subprocess.CalledProcessError(-1, '')
+        self.assertEqual(runner_base._execute_shell_command("")[0], -1)
 
-        base._single_action(0, "echo", mock.MagicMock())
+    @mock.patch.object(subprocess, 'check_output')
+    def test__single_action(self, mock_subprocess):
+        mock_subprocess.side_effect = subprocess.CalledProcessError(-1, '')
+        runner_base._single_action(0, 'echo', mock.Mock())
 
-    @mock.patch("yardstick.benchmark.runners.base.subprocess")
+    @mock.patch.object(subprocess, 'check_output')
     def test__periodic_action(self, mock_subprocess):
-        mock_subprocess.check_output.side_effect = CalledProcessError(-1, '')
-
-        base._periodic_action(0, "echo", mock.MagicMock())
+        mock_subprocess.side_effect = subprocess.CalledProcessError(-1, '')
+        runner_base._periodic_action(0, 'echo', mock.Mock())
 
 
-class RunnerTestCase(unittest.TestCase):
+class RunnerTestCase(ut_base.BaseUnitTestCase):
 
     def setUp(self):
         config = {
@@ -86,7 +95,58 @@ class RunnerTestCase(unittest.TestCase):
         self.assertEqual(idle_result, actual_result)
 
     def test__run_benchmark(self):
-        runner = base.Runner(mock.Mock())
+        runner = runner_base.Runner(mock.Mock())
 
         with self.assertRaises(NotImplementedError):
             runner._run_benchmark(mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock())
+
+
+class RunnerProducerTestCase(ut_base.BaseUnitTestCase):
+
+    @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
+    @mock.patch.object(oslo_messaging, 'RPCClient')
+    @mock.patch.object(oslo_messaging, 'get_rpc_transport',
+                       return_value='rpc_transport')
+    @mock.patch.object(cfg, 'CONF')
+    def test__init(self, mock_config, mock_transport, mock_rpcclient,
+                   mock_target):
+        _id = uuid.uuid1().int
+        runner_producer = runner_base.RunnerProducer(_id)
+        mock_transport.assert_called_once_with(
+            mock_config, url='rabbit://yardstick:yardstick@localhost:5672/')
+        mock_target.assert_called_once_with(topic=messaging.TOPIC_RUNNER,
+                                            fanout=True,
+                                            server=messaging.SERVER)
+        mock_rpcclient.assert_called_once_with('rpc_transport', 'rpc_target')
+        self.assertEqual(_id, runner_producer._id)
+        self.assertEqual(messaging.TOPIC_RUNNER, runner_producer._topic)
+
+    @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
+    @mock.patch.object(oslo_messaging, 'RPCClient')
+    @mock.patch.object(oslo_messaging, 'get_rpc_transport',
+                       return_value='rpc_transport')
+    @mock.patch.object(payloads, 'RunnerPayload', return_value='runner_pload')
+    def test_start_iteration(self, mock_runner_payload, *args):
+        runner_producer = runner_base.RunnerProducer(uuid.uuid1().int)
+        with mock.patch.object(runner_producer,
+                               'send_message') as mock_message:
+            runner_producer.start_iteration(version=10)
+
+        mock_message.assert_called_once_with(
+            messaging.RUNNER_METHOD_START_ITERATION, 'runner_pload')
+        mock_runner_payload.assert_called_once_with(version=10, data={})
+
+    @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
+    @mock.patch.object(oslo_messaging, 'RPCClient')
+    @mock.patch.object(oslo_messaging, 'get_rpc_transport',
+                       return_value='rpc_transport')
+    @mock.patch.object(payloads, 'RunnerPayload', return_value='runner_pload')
+    def test_stop_iteration(self, mock_runner_payload, *args):
+        runner_producer = runner_base.RunnerProducer(uuid.uuid1().int)
+        with mock.patch.object(runner_producer,
+                               'send_message') as mock_message:
+            runner_producer.stop_iteration(version=15)
+
+        mock_message.assert_called_once_with(
+            messaging.RUNNER_METHOD_STOP_ITERATION, 'runner_pload')
+        mock_runner_payload.assert_called_once_with(version=15, data={})
diff --git a/yardstick/tests/unit/benchmark/runner/test_duration.py b/yardstick/tests/unit/benchmark/runner/test_duration.py
new file mode 100644 (file)
index 0000000..21e3874
--- /dev/null
@@ -0,0 +1,39 @@
+##############################################################################
+# Copyright (c) 2018 Nokia and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+import mock
+import unittest
+import multiprocessing
+import os
+
+from yardstick.benchmark.runners import duration
+
+
+class DurationRunnerTest(unittest.TestCase):
+    def setUp(self):
+        self.scenario_cfg = {
+            'runner': {'interval': 0, "duration": 0},
+            'type': 'some_type'
+        }
+
+    @mock.patch.object(os, 'getpid')
+    @mock.patch.object(multiprocessing, 'Process')
+    def test__run_benchmark_called_with(self, mock_multiprocessing_process,
+                                        mock_os_getpid):
+        mock_os_getpid.return_value = 101
+
+        runner = duration.DurationRunner({})
+        benchmark_cls = mock.Mock()
+        runner._run_benchmark(benchmark_cls, 'my_method', self.scenario_cfg,
+                              {})
+        mock_multiprocessing_process.assert_called_once_with(
+            name='Duration-some_type-101',
+            target=duration._worker_process,
+            args=(runner.result_queue, benchmark_cls, 'my_method',
+                  self.scenario_cfg, {}, runner.aborted, runner.output_queue))
diff --git a/yardstick/tests/unit/benchmark/runner/test_iteration_ipc.py b/yardstick/tests/unit/benchmark/runner/test_iteration_ipc.py
new file mode 100644 (file)
index 0000000..10d14a8
--- /dev/null
@@ -0,0 +1,136 @@
+# Copyright (c) 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.
+
+import multiprocessing
+import time
+import os
+import uuid
+
+import mock
+
+from yardstick.benchmark.runners import iteration_ipc
+from yardstick.common import messaging
+from yardstick.common.messaging import payloads
+from yardstick.tests.unit import base as ut_base
+
+
+class RunnerIterationIPCEndpointTestCase(ut_base.BaseUnitTestCase):
+
+    def setUp(self):
+        self._id = uuid.uuid1().int
+        self._ctx_ids = [uuid.uuid1().int, uuid.uuid1().int]
+        self._queue = multiprocessing.Queue()
+        self.runner = iteration_ipc.RunnerIterationIPCEndpoint(
+            self._id, self._ctx_ids, self._queue)
+        self._kwargs = {'version': 1, 'iteration': 10, 'kpi': {}}
+        self._pload_dict = payloads.TrafficGeneratorPayload.dict_to_obj(
+            self._kwargs).obj_to_dict()
+
+    def test_tg_method_started(self):
+        self._queue.empty()
+        ctxt = {'id': self._ctx_ids[0]}
+        self.runner.tg_method_started(ctxt, **self._kwargs)
+        time.sleep(0.2)
+
+        output = []
+        while not self._queue.empty():
+            output.append(self._queue.get(True, 1))
+
+        self.assertEqual(1, len(output))
+        self.assertEqual(self._ctx_ids[0], output[0]['id'])
+        self.assertEqual(messaging.TG_METHOD_STARTED, output[0]['action'])
+        self.assertEqual(self._pload_dict, output[0]['payload'].obj_to_dict())
+
+    def test_tg_method_finished(self):
+        self._queue.empty()
+        ctxt = {'id': self._ctx_ids[0]}
+        self.runner.tg_method_finished(ctxt, **self._kwargs)
+        time.sleep(0.2)
+
+        output = []
+        while not self._queue.empty():
+            output.append(self._queue.get(True, 1))
+
+        self.assertEqual(1, len(output))
+        self.assertEqual(self._ctx_ids[0], output[0]['id'])
+        self.assertEqual(messaging.TG_METHOD_FINISHED, output[0]['action'])
+        self.assertEqual(self._pload_dict, output[0]['payload'].obj_to_dict())
+
+    def test_tg_method_iteration(self):
+        self._queue.empty()
+        ctxt = {'id': self._ctx_ids[0]}
+        self.runner.tg_method_iteration(ctxt, **self._kwargs)
+        time.sleep(0.2)
+
+        output = []
+        while not self._queue.empty():
+            output.append(self._queue.get(True, 1))
+
+        self.assertEqual(1, len(output))
+        self.assertEqual(self._ctx_ids[0], output[0]['id'])
+        self.assertEqual(messaging.TG_METHOD_ITERATION, output[0]['action'])
+        self.assertEqual(self._pload_dict, output[0]['payload'].obj_to_dict())
+
+
+class RunnerIterationIPCConsumerTestCase(ut_base.BaseUnitTestCase):
+
+    def setUp(self):
+        self._id = uuid.uuid1().int
+        self._ctx_ids = [uuid.uuid1().int, uuid.uuid1().int]
+        self.consumer = iteration_ipc.RunnerIterationIPCConsumer(
+            self._id, self._ctx_ids)
+        self.consumer._queue = mock.Mock()
+
+    def test__init(self):
+        self.assertEqual({self._ctx_ids[0]: [], self._ctx_ids[1]: []},
+                         self.consumer._kpi_per_id)
+
+    def test_is_all_kpis_received_in_iteration(self):
+        payload = payloads.TrafficGeneratorPayload(
+            version=1, iteration=1, kpi={})
+        msg1 = {'action': messaging.TG_METHOD_ITERATION,
+                'id': self._ctx_ids[0], 'payload': payload}
+        msg2 = {'action': messaging.TG_METHOD_ITERATION,
+                'id': self._ctx_ids[1], 'payload': payload}
+        self.consumer.iteration_index = 1
+
+        self.consumer._queue.empty.side_effect = [False, True]
+        self.consumer._queue.get.return_value = msg1
+        self.assertFalse(self.consumer.is_all_kpis_received_in_iteration())
+
+        self.consumer._queue.empty.side_effect = [False, True]
+        self.consumer._queue.get.return_value = msg2
+        self.assertTrue(self.consumer.is_all_kpis_received_in_iteration())
+
+
+class IterationIPCRunnerTestCase(ut_base.BaseUnitTestCase):
+
+    @mock.patch.object(iteration_ipc, '_worker_process')
+    @mock.patch.object(os, 'getpid', return_value=12345678)
+    @mock.patch.object(multiprocessing, 'Process', return_value=mock.Mock())
+    def test__run_benchmark(self, mock_process, mock_getpid, mock_worker):
+        method = 'method'
+        scenario_cfg = {'type': 'scenario_type'}
+        context_cfg = 'context_cfg'
+        name = '%s-%s-%s' % ('IterationIPC', 'scenario_type', 12345678)
+        runner = iteration_ipc.IterationIPCRunner(mock.ANY)
+        mock_getpid.reset_mock()
+
+        runner._run_benchmark('class', method, scenario_cfg, context_cfg)
+        mock_process.assert_called_once_with(
+            name=name,
+            target=mock_worker,
+            args=(runner.result_queue, 'class', method, scenario_cfg,
+                  context_cfg, runner.aborted, runner.output_queue))
+        mock_getpid.assert_called_once()
diff --git a/yardstick/tests/unit/benchmark/runner/test_proxduration.py b/yardstick/tests/unit/benchmark/runner/test_proxduration.py
new file mode 100644 (file)
index 0000000..3299c5b
--- /dev/null
@@ -0,0 +1,286 @@
+# Copyright (c) 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.
+
+import mock
+import unittest
+import multiprocessing
+import os
+
+from yardstick.benchmark.runners import proxduration
+from yardstick.common import constants
+from yardstick.common import exceptions as y_exc
+
+
+class ProxDurationRunnerTest(unittest.TestCase):
+
+    class MyMethod(object):
+        SLA_VALIDATION_ERROR_SIDE_EFFECT = 1
+        BROAD_EXCEPTION_SIDE_EFFECT = 2
+
+        def __init__(self, side_effect=0):
+            self.count = 101
+            self.side_effect = side_effect
+
+        def __call__(self, data):
+            self.count += 1
+            data['my_key'] = self.count
+            if self.side_effect == self.SLA_VALIDATION_ERROR_SIDE_EFFECT:
+                raise y_exc.SLAValidationError(case_name='My Case',
+                                               error_msg='my error message')
+            elif self.side_effect == self.BROAD_EXCEPTION_SIDE_EFFECT:
+                raise y_exc.YardstickException
+            return self.count
+
+    def setUp(self):
+        self.scenario_cfg = {
+            'runner': {'interval': 0, "duration": 0},
+            'type': 'some_type'
+        }
+
+        self.benchmark = mock.Mock()
+        self.benchmark_cls = mock.Mock(return_value=self.benchmark)
+
+    def _assert_defaults__worker_run_setup_and_teardown(self):
+        self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+        self.benchmark.setup.assert_called_once()
+        self.benchmark.teardown.assert_called_once()
+
+    @mock.patch.object(os, 'getpid')
+    @mock.patch.object(multiprocessing, 'Process')
+    def test__run_benchmark_called_with(self, mock_multiprocessing_process,
+                                        mock_os_getpid):
+        mock_os_getpid.return_value = 101
+
+        runner = proxduration.ProxDurationRunner({})
+        benchmark_cls = mock.Mock()
+        runner._run_benchmark(benchmark_cls, 'my_method', self.scenario_cfg,
+                              {})
+        mock_multiprocessing_process.assert_called_once_with(
+            name='ProxDuration-some_type-101',
+            target=proxduration._worker_process,
+            args=(runner.result_queue, benchmark_cls, 'my_method',
+                  self.scenario_cfg, {}, runner.aborted, runner.output_queue))
+
+    @mock.patch.object(os, 'getpid')
+    def test__worker_process_runner_id(self, mock_os_getpid):
+        mock_os_getpid.return_value = 101
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        proxduration._worker_process(
+            mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+            {}, multiprocessing.Event(), mock.Mock())
+
+        self.assertEqual(101, self.scenario_cfg['runner']['runner_id'])
+
+    def test__worker_process_called_with_cfg(self):
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        proxduration._worker_process(
+            mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+            {}, multiprocessing.Event(), mock.Mock())
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+
+    def test__worker_process_called_with_cfg_loop(self):
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        proxduration._worker_process(
+            mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+            {}, multiprocessing.Event(), mock.Mock())
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+        self.assertGreater(self.benchmark.my_method.call_count, 2)
+
+    def test__worker_process_called_without_cfg(self):
+        scenario_cfg = {'runner': {}}
+        aborted = multiprocessing.Event()
+        aborted.set()
+        proxduration._worker_process(
+            mock.Mock(), self.benchmark_cls, 'my_method', scenario_cfg, {},
+            aborted, mock.Mock())
+
+        self.benchmark_cls.assert_called_once_with(scenario_cfg, {})
+        self.benchmark.setup.assert_called_once()
+        self.benchmark.teardown.assert_called_once()
+
+    def test__worker_process_output_queue(self):
+        self.benchmark.my_method = mock.Mock(return_value='my_result')
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        output_queue = mock.Mock()
+        proxduration._worker_process(
+            mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+            {}, multiprocessing.Event(), output_queue)
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+        output_queue.put.assert_has_calls(
+            [mock.call('my_result', True, constants.QUEUE_PUT_TIMEOUT)])
+
+    def test__worker_process_output_queue_multiple_iterations(self):
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        self.benchmark.my_method = self.MyMethod()
+        output_queue = mock.Mock()
+        proxduration._worker_process(
+            mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+            {}, multiprocessing.Event(), output_queue)
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+        for idx in range(102, 101 + len(output_queue.method_calls)):
+            output_queue.put.assert_has_calls(
+                [mock.call(idx, True, constants.QUEUE_PUT_TIMEOUT)])
+
+    def test__worker_process_queue(self):
+        self.benchmark.my_method = self.MyMethod()
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        queue = mock.Mock()
+        proxduration._worker_process(
+            queue, self.benchmark_cls, 'my_method', self.scenario_cfg, {},
+            multiprocessing.Event(), mock.Mock())
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+        benchmark_output = {'timestamp': mock.ANY,
+                            'sequence': 1,
+                            'data': {'my_key': 102},
+                            'errors': ''}
+        queue.put.assert_has_calls(
+            [mock.call(benchmark_output, True, constants.QUEUE_PUT_TIMEOUT)])
+
+    def test__worker_process_queue_multiple_iterations(self):
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        self.benchmark.my_method = self.MyMethod()
+        queue = mock.Mock()
+        proxduration._worker_process(
+            queue, self.benchmark_cls, 'my_method', self.scenario_cfg, {},
+            multiprocessing.Event(), mock.Mock())
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+        for idx in range(102, 101 + len(queue.method_calls)):
+            benchmark_output = {'timestamp': mock.ANY,
+                                'sequence': idx - 101,
+                                'data': {'my_key': idx},
+                                'errors': ''}
+            queue.put.assert_has_calls(
+                [mock.call(benchmark_output, True,
+                           constants.QUEUE_PUT_TIMEOUT)])
+
+    def test__worker_process_except_sla_validation_error_no_sla_cfg(self):
+        self.benchmark.my_method = mock.Mock(
+            side_effect=y_exc.SLAValidationError)
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        proxduration._worker_process(
+            mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+            {}, multiprocessing.Event(), mock.Mock())
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+
+    @mock.patch.object(proxduration.LOG, 'warning')
+    def test__worker_process_except_sla_validation_error_sla_cfg_monitor(
+            self, *args):
+        self.scenario_cfg['sla'] = {'action': 'monitor'}
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        self.benchmark.my_method = mock.Mock(
+            side_effect=y_exc.SLAValidationError)
+        proxduration._worker_process(
+            mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+            {}, multiprocessing.Event(), mock.Mock())
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+
+    def test__worker_process_raise_sla_validation_error_sla_cfg_default(self):
+        self.scenario_cfg['sla'] = {}
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        self.benchmark.my_method = mock.Mock(
+            side_effect=y_exc.SLAValidationError)
+        with self.assertRaises(y_exc.SLAValidationError):
+            proxduration._worker_process(
+                mock.Mock(), self.benchmark_cls, 'my_method',
+                self.scenario_cfg, {}, multiprocessing.Event(), mock.Mock())
+
+        self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+        self.benchmark.setup.assert_called_once()
+        self.benchmark.my_method.assert_called_once_with({})
+
+    def test__worker_process_raise_sla_validation_error_sla_cfg_assert(self):
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        self.scenario_cfg['sla'] = {'action': 'assert'}
+        self.benchmark.my_method = mock.Mock(
+            side_effect=y_exc.SLAValidationError)
+
+        with self.assertRaises(y_exc.SLAValidationError):
+            proxduration._worker_process(
+                mock.Mock(), self.benchmark_cls, 'my_method',
+                self.scenario_cfg, {}, multiprocessing.Event(), mock.Mock())
+
+        self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+        self.benchmark.setup.assert_called_once()
+        self.benchmark.my_method.assert_called_once_with({})
+
+    @mock.patch.object(proxduration.LOG, 'warning')
+    def test__worker_process_queue_on_sla_validation_error_monitor(
+            self, *args):
+        self.scenario_cfg['sla'] = {'action': 'monitor'}
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        self.benchmark.my_method = self.MyMethod(
+            side_effect=self.MyMethod.SLA_VALIDATION_ERROR_SIDE_EFFECT)
+        queue = mock.Mock()
+        proxduration._worker_process(
+            queue, self.benchmark_cls, 'my_method', self.scenario_cfg, {},
+            multiprocessing.Event(), mock.Mock())
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+        benchmark_output = {'timestamp': mock.ANY,
+                            'sequence': 1,
+                            'data': {'my_key': 102},
+                            'errors': ('My Case SLA validation failed. '
+                                       'Error: my error message', )}
+        queue.put.assert_has_calls(
+            [mock.call(benchmark_output, True, constants.QUEUE_PUT_TIMEOUT)])
+
+    @mock.patch.object(proxduration.LOG, 'exception')
+    def test__worker_process_broad_exception(self, *args):
+        self.benchmark.my_method = mock.Mock(
+            side_effect=y_exc.YardstickException)
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        proxduration._worker_process(
+            mock.Mock(), self.benchmark_cls, 'my_method',
+            self.scenario_cfg, {}, multiprocessing.Event(), mock.Mock())
+
+        self._assert_defaults__worker_run_setup_and_teardown()
+
+    @mock.patch.object(proxduration.LOG, 'exception')
+    def test__worker_process_queue_on_broad_exception(self, *args):
+        self.benchmark.my_method = self.MyMethod(
+            side_effect=self.MyMethod.BROAD_EXCEPTION_SIDE_EFFECT)
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+        queue = mock.Mock()
+        proxduration._worker_process(
+            queue, self.benchmark_cls, 'my_method', self.scenario_cfg, {},
+            multiprocessing.Event(), mock.Mock())
+
+        benchmark_output = {'timestamp': mock.ANY,
+                            'sequence': 1,
+                            'data': {'my_key': 102},
+                            'errors': mock.ANY}
+        queue.put.assert_has_calls(
+            [mock.call(benchmark_output, True, constants.QUEUE_PUT_TIMEOUT)])
+
+    @mock.patch.object(proxduration.LOG, 'exception')
+    def test__worker_process_benchmark_teardown_on_broad_exception(
+            self, *args):
+        self.benchmark.teardown = mock.Mock(
+            side_effect=y_exc.YardstickException)
+        self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+
+        with self.assertRaises(SystemExit) as raised:
+            proxduration._worker_process(
+                mock.Mock(), self.benchmark_cls, 'my_method',
+                self.scenario_cfg, {}, multiprocessing.Event(), mock.Mock())
+        self.assertEqual(1, raised.exception.code)
+        self._assert_defaults__worker_run_setup_and_teardown()
index 4e5b4fe..d5d1b8d 100644 (file)
@@ -19,36 +19,33 @@ import unittest
 
 from yardstick.benchmark.runners.search import SearchRunner
 from yardstick.benchmark.runners.search import SearchRunnerHelper
+from yardstick.common import exceptions as y_exc
 
 
 class TestSearchRunnerHelper(unittest.TestCase):
 
     def test___call__(self):
-        cls = mock.MagicMock()
-        aborted = mock.MagicMock()
         scenario_cfg = {
             'runner': {},
         }
 
-        benchmark = cls()
-        method = getattr(benchmark, 'my_method')
+        benchmark = mock.Mock()
+        method = getattr(benchmark(), 'my_method')
         helper = SearchRunnerHelper(
-            cls, 'my_method', scenario_cfg, {}, aborted)
+            benchmark, 'my_method', scenario_cfg, {}, mock.Mock())
 
         with helper.get_benchmark_instance():
             helper()
 
-        self.assertEqual(method.call_count, 1)
+        method.assert_called_once()
 
     def test___call___error(self):
-        cls = mock.MagicMock()
-        aborted = mock.MagicMock()
         scenario_cfg = {
             'runner': {},
         }
 
         helper = SearchRunnerHelper(
-            cls, 'my_method', scenario_cfg, {}, aborted)
+            mock.Mock(), 'my_method', scenario_cfg, {}, mock.Mock())
 
         with self.assertRaises(RuntimeError):
             helper()
@@ -56,8 +53,6 @@ class TestSearchRunnerHelper(unittest.TestCase):
     @mock.patch.object(time, 'sleep')
     @mock.patch.object(time, 'time')
     def test_is_not_done(self, mock_time, *args):
-        cls = mock.MagicMock()
-        aborted = mock.MagicMock()
         scenario_cfg = {
             'runner': {},
         }
@@ -65,7 +60,7 @@ class TestSearchRunnerHelper(unittest.TestCase):
         mock_time.side_effect = range(1000)
 
         helper = SearchRunnerHelper(
-            cls, 'my_method', scenario_cfg, {}, aborted)
+            mock.Mock(), 'my_method', scenario_cfg, {}, mock.Mock())
 
         index = -1
         for index in helper.is_not_done():
@@ -76,8 +71,6 @@ class TestSearchRunnerHelper(unittest.TestCase):
 
     @mock.patch.object(time, 'sleep')
     def test_is_not_done_immediate_stop(self, *args):
-        cls = mock.MagicMock()
-        aborted = mock.MagicMock()
         scenario_cfg = {
             'runner': {
                 'run_step': '',
@@ -85,7 +78,7 @@ class TestSearchRunnerHelper(unittest.TestCase):
         }
 
         helper = SearchRunnerHelper(
-            cls, 'my_method', scenario_cfg, {}, aborted)
+            mock.Mock(), 'my_method', scenario_cfg, {}, mock.Mock())
 
         index = -1
         for index in helper.is_not_done():
@@ -112,7 +105,7 @@ class TestSearchRunner(unittest.TestCase):
         }
 
         runner = SearchRunner({})
-        runner.worker_helper = mock.MagicMock(side_effect=update)
+        runner.worker_helper = mock.Mock(side_effect=update)
 
         self.assertFalse(runner._worker_run_once('sequence 1'))
 
@@ -136,51 +129,49 @@ class TestSearchRunner(unittest.TestCase):
         }
 
         runner = SearchRunner({})
-        runner.worker_helper = mock.MagicMock(side_effect=update)
+        runner.worker_helper = mock.Mock(side_effect=update)
 
         self.assertTrue(runner._worker_run_once('sequence 1'))
 
     def test__worker_run_once_assertion_error_assert(self):
         runner = SearchRunner({})
         runner.sla_action = 'assert'
-        runner.worker_helper = mock.MagicMock(side_effect=AssertionError)
+        runner.worker_helper = mock.Mock(side_effect=y_exc.SLAValidationError)
 
-        with self.assertRaises(AssertionError):
+        with self.assertRaises(y_exc.SLAValidationError):
             runner._worker_run_once('sequence 1')
 
     def test__worker_run_once_assertion_error_monitor(self):
         runner = SearchRunner({})
         runner.sla_action = 'monitor'
-        runner.worker_helper = mock.MagicMock(side_effect=AssertionError)
+        runner.worker_helper = mock.Mock(side_effect=y_exc.SLAValidationError)
 
         self.assertFalse(runner._worker_run_once('sequence 1'))
 
     def test__worker_run_once_non_assertion_error_none(self):
         runner = SearchRunner({})
-        runner.worker_helper = mock.MagicMock(side_effect=RuntimeError)
+        runner.worker_helper = mock.Mock(side_effect=RuntimeError)
 
         self.assertTrue(runner._worker_run_once('sequence 1'))
 
     def test__worker_run_once_non_assertion_error(self):
         runner = SearchRunner({})
         runner.sla_action = 'monitor'
-        runner.worker_helper = mock.MagicMock(side_effect=RuntimeError)
+        runner.worker_helper = mock.Mock(side_effect=RuntimeError)
 
         self.assertFalse(runner._worker_run_once('sequence 1'))
 
     def test__worker_run(self):
-        cls = mock.MagicMock()
         scenario_cfg = {
             'runner': {'interval': 0, 'timeout': 1},
         }
 
         runner = SearchRunner({})
-        runner._worker_run_once = mock.MagicMock(side_effect=[0, 0, 1])
+        runner._worker_run_once = mock.Mock(side_effect=[0, 0, 1])
 
-        runner._worker_run(cls, 'my_method', scenario_cfg, {})
+        runner._worker_run(mock.Mock(), 'my_method', scenario_cfg, {})
 
     def test__worker_run_immediate_stop(self):
-        cls = mock.MagicMock()
         scenario_cfg = {
             'runner': {
                 'run_step': '',
@@ -188,15 +179,14 @@ class TestSearchRunner(unittest.TestCase):
         }
 
         runner = SearchRunner({})
-        runner._worker_run(cls, 'my_method', scenario_cfg, {})
+        runner._worker_run(mock.Mock(), 'my_method', scenario_cfg, {})
 
     @mock.patch('yardstick.benchmark.runners.search.multiprocessing')
     def test__run_benchmark(self, mock_multi_process):
-        cls = mock.MagicMock()
         scenario_cfg = {
             'runner': {},
         }
 
         runner = SearchRunner({})
-        runner._run_benchmark(cls, 'my_method', scenario_cfg, {})
-        self.assertEqual(mock_multi_process.Process.call_count, 1)
+        runner._run_benchmark(mock.Mock(), 'my_method', scenario_cfg, {})
+        mock_multi_process.Process.assert_called_once()
index ce97277..8d042c4 100644 (file)
@@ -7,6 +7,8 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
+import time
+
 import mock
 import unittest
 
@@ -86,13 +88,19 @@ class BaseMonitorTestCase(unittest.TestCase):
             'sla': {'max_outage_time': 5}
         }
 
+    def _close_queue(self, instace):
+        time.sleep(0.1)
+        instace._queue.close()
+
     def test__basemonitor_start_wait_successful(self):
         ins = basemonitor.BaseMonitor(self.monitor_cfg, None, {"nova-api": 10})
+        self.addCleanup(self._close_queue, ins)
         ins.start_monitor()
         ins.wait_monitor()
 
     def test__basemonitor_all_successful(self):
         ins = self.MonitorSimple(self.monitor_cfg, None, {"nova-api": 10})
+        self.addCleanup(self._close_queue, ins)
         ins.setup()
         ins.run()
         ins.verify_SLA()
@@ -100,16 +108,12 @@ class BaseMonitorTestCase(unittest.TestCase):
     @mock.patch.object(basemonitor, 'multiprocessing')
     def test__basemonitor_func_false(self, mock_multiprocess):
         ins = self.MonitorSimple(self.monitor_cfg, None, {"nova-api": 10})
+        self.addCleanup(self._close_queue, ins)
         ins.setup()
         mock_multiprocess.Event().is_set.return_value = False
         ins.run()
         ins.verify_SLA()
 
-    # TODO(elfoley): fix this test to not throw an error
     def test__basemonitor_getmonitorcls_successfule(self):
-        cls = None
-        try:
-            cls = basemonitor.BaseMonitor.get_monitor_cls(self.monitor_cfg)
-        except Exception:  # pylint: disable=broad-except
-            pass
-        self.assertIsNone(cls)
+        with self.assertRaises(RuntimeError):
+            basemonitor.BaseMonitor.get_monitor_cls(self.monitor_cfg)
index d1172d5..dbf3d83 100644 (file)
@@ -11,6 +11,8 @@ import mock
 import unittest
 
 from yardstick.benchmark.scenarios.availability import scenario_general
+from yardstick.common import exceptions as y_exc
+
 
 class ScenarioGeneralTestCase(unittest.TestCase):
 
@@ -36,19 +38,21 @@ class ScenarioGeneralTestCase(unittest.TestCase):
                         'index': 2}]
             }
         }
-        self.instance = scenario_general.ScenarioGeneral(self.scenario_cfg, None)
+        self.instance = scenario_general.ScenarioGeneral(self.scenario_cfg,
+                                                         None)
         self.instance.setup()
         self.instance.director.verify.return_value = True
 
     def test_scenario_general_all_successful(self):
-
         ret = {}
         self.instance.run(ret)
         self.instance.teardown()
         self.assertEqual(ret['sla_pass'], 1)
 
-    def test_scenario_general_exception(self):
-        self.instance.director.createActionPlayer.side_effect = KeyError('Wrong')
+    @mock.patch.object(scenario_general.LOG, 'exception')
+    def test_scenario_general_exception(self, *args):
+        self.instance.director.createActionPlayer.side_effect = (
+            KeyError('Wrong'))
         self.instance.director.data = {}
         ret = {}
         self.instance.run(ret)
@@ -59,6 +63,14 @@ class ScenarioGeneralTestCase(unittest.TestCase):
         self.instance.director.verify.return_value = False
         self.instance.director.data = {}
         ret = {}
-        self.assertRaises(AssertionError, self.instance.run, ret)
+        self.assertRaises(y_exc.SLAValidationError, self.instance.run, ret)
+        self.instance.teardown()
+        self.assertEqual(ret['sla_pass'], 0)
+
+    def test_scenario_general_case_service_not_found_fail(self):
+        self.instance.director.verify.return_value = True
+        self.instance.director.data = {"general-attacker": 0}
+        ret = {}
+        self.assertRaises(y_exc.SLAValidationError, self.instance.run, ret)
         self.instance.teardown()
         self.assertEqual(ret['sla_pass'], 0)
index dd656fb..ec0e597 100644 (file)
@@ -11,6 +11,7 @@ import mock
 import unittest
 
 from yardstick.benchmark.scenarios.availability import serviceha
+from yardstick.common import exceptions as y_exc
 
 
 class ServicehaTestCase(unittest.TestCase):
@@ -42,6 +43,13 @@ class ServicehaTestCase(unittest.TestCase):
         }
         sla = {"outage_time": 5}
         self.args = {"options": options, "sla": sla}
+        self.test__serviceha = serviceha.ServiceHA(self.args, self.ctx)
+
+    def test___init__(self):
+
+        self.assertEqual(self.test__serviceha.data, {})
+        self.assertFalse(self.test__serviceha.setup_done)
+        self.assertFalse(self.test__serviceha.sla_pass)
 
     # NOTE(elfoley): This should be split into test_setup and test_run
     # NOTE(elfoley): This should explicitly test outcomes and states
@@ -71,5 +79,36 @@ class ServicehaTestCase(unittest.TestCase):
         mock_monitor.MonitorMgr().verify_SLA.return_value = False
 
         ret = {}
-        self.assertRaises(AssertionError, p.run, ret)
+        self.assertRaises(y_exc.SLAValidationError, p.run, ret)
+        self.assertEqual(ret['sla_pass'], 0)
+
+    @mock.patch.object(serviceha, 'baseattacker')
+    @mock.patch.object(serviceha, 'basemonitor')
+    def test__serviceha_run_service_not_found_sla_error(self, mock_monitor,
+                                                        *args):
+        p = serviceha.ServiceHA(self.args, self.ctx)
+
+        p.setup()
+        self.assertTrue(p.setup_done)
+        p.data["kill-process"] = 0
+
+        mock_monitor.MonitorMgr().verify_SLA.return_value = True
+
+        ret = {}
+        self.assertRaises(y_exc.SLAValidationError, p.run, ret)
         self.assertEqual(ret['sla_pass'], 0)
+
+    @mock.patch.object(serviceha, 'baseattacker')
+    @mock.patch.object(serviceha, 'basemonitor')
+    def test__serviceha_no_teardown_when_sla_pass(self, mock_monitor,
+                                                  *args):
+        p = serviceha.ServiceHA(self.args, self.ctx)
+        p.setup()
+        self.assertTrue(p.setup_done)
+        mock_monitor.MonitorMgr().verify_SLA.return_value = True
+        ret = {}
+        p.run(ret)
+        attacker = mock.Mock()
+        p.attackers = [attacker]
+        p.teardown()
+        attacker.recover.assert_not_called()
index f24ec24..4fadde4 100644 (file)
@@ -17,6 +17,7 @@ import mock
 from oslo_serialization import jsonutils
 
 from yardstick.benchmark.scenarios.compute import cyclictest
+from yardstick.common import exceptions as y_exc
 
 
 @mock.patch('yardstick.benchmark.scenarios.compute.cyclictest.ssh')
@@ -122,7 +123,7 @@ class CyclictestTestCase(unittest.TestCase):
         sample_output = '{"min": 100, "avg": 500, "max": 1000}'
 
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, c.run, result)
+        self.assertRaises(y_exc.SLAValidationError, c.run, result)
 
     def test_cyclictest_unsuccessful_sla_avg_latency(self, mock_ssh):
 
@@ -136,7 +137,7 @@ class CyclictestTestCase(unittest.TestCase):
         sample_output = '{"min": 100, "avg": 500, "max": 1000}'
 
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, c.run, result)
+        self.assertRaises(y_exc.SLAValidationError, c.run, result)
 
     def test_cyclictest_unsuccessful_sla_max_latency(self, mock_ssh):
 
@@ -150,7 +151,7 @@ class CyclictestTestCase(unittest.TestCase):
         sample_output = '{"min": 100, "avg": 500, "max": 1000}'
 
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, c.run, result)
+        self.assertRaises(y_exc.SLAValidationError, c.run, result)
 
     def test_cyclictest_unsuccessful_script_error(self, mock_ssh):
 
index 9640ce0..c4ac347 100644 (file)
@@ -17,6 +17,7 @@ import mock
 from oslo_serialization import jsonutils
 
 from yardstick.benchmark.scenarios.compute import lmbench
+from yardstick.common import exceptions as y_exc
 
 
 # pylint: disable=unused-argument
@@ -144,7 +145,7 @@ class LmbenchTestCase(unittest.TestCase):
 
         sample_output = '[{"latency": 37.5, "size": 0.00049}]'
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, l.run, self.result)
+        self.assertRaises(y_exc.SLAValidationError, l.run, self.result)
 
     def test_unsuccessful_bandwidth_run_sla(self, mock_ssh):
 
@@ -162,7 +163,7 @@ class LmbenchTestCase(unittest.TestCase):
 
         sample_output = '{"size(MB)": 0.262144, "bandwidth(MBps)": 9925.5}'
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, l.run, self.result)
+        self.assertRaises(y_exc.SLAValidationError, l.run, self.result)
 
     def test_successful_latency_for_cache_run_sla(self, mock_ssh):
 
index 03003d0..02040ca 100644 (file)
@@ -17,6 +17,7 @@ import mock
 from oslo_serialization import jsonutils
 
 from yardstick.benchmark.scenarios.compute import qemu_migrate
+from yardstick.common import exceptions as y_exc
 
 
 @mock.patch('yardstick.benchmark.scenarios.compute.qemu_migrate.ssh')
@@ -116,7 +117,7 @@ class QemuMigrateTestCase(unittest.TestCase):
         sample_output = '{"totaltime": 15, "downtime": 2, "setuptime": 1}'
 
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, q.run, result)
+        self.assertRaises(y_exc.SLAValidationError, q.run, result)
 
     def test_qemu_migrate_unsuccessful_sla_downtime(self, mock_ssh):
 
@@ -129,7 +130,7 @@ class QemuMigrateTestCase(unittest.TestCase):
         sample_output = '{"totaltime": 15, "downtime": 2, "setuptime": 1}'
 
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, q.run, result)
+        self.assertRaises(y_exc.SLAValidationError, q.run, result)
 
     def test_qemu_migrate_unsuccessful_sla_setuptime(self, mock_ssh):
 
@@ -142,7 +143,7 @@ class QemuMigrateTestCase(unittest.TestCase):
         sample_output = '{"totaltime": 15, "downtime": 2, "setuptime": 1}'
 
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, q.run, result)
+        self.assertRaises(y_exc.SLAValidationError, q.run, result)
 
     def test_qemu_migrate_unsuccessful_script_error(self, mock_ssh):
 
index dcc0e81..9e055be 100644 (file)
@@ -18,6 +18,7 @@ from oslo_serialization import jsonutils
 
 from yardstick.common import utils
 from yardstick.benchmark.scenarios.compute import ramspeed
+from yardstick.common import exceptions as y_exc
 
 
 @mock.patch('yardstick.benchmark.scenarios.compute.ramspeed.ssh')
@@ -146,7 +147,7 @@ class RamspeedTestCase(unittest.TestCase):
  "Block_size(kb)": 16384, "Bandwidth(MBps)": 14128.94}, {"Test_type":\
  "INTEGER & WRITING", "Block_size(kb)": 32768, "Bandwidth(MBps)": 8340.85}]}'
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, r.run, self.result)
+        self.assertRaises(y_exc.SLAValidationError, r.run, self.result)
 
     def test_ramspeed_unsuccessful_script_error(self, mock_ssh):
         options = {
@@ -219,7 +220,7 @@ class RamspeedTestCase(unittest.TestCase):
  "Bandwidth(MBps)": 1300.27}, {"Test_type": "INTEGER AVERAGE:",\
  "Bandwidth(MBps)": 2401.58}]}'
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, r.run, self.result)
+        self.assertRaises(y_exc.SLAValidationError, r.run, self.result)
 
     def test_ramspeed_unsuccessful_unknown_type_run(self, mock_ssh):
         options = {
index 6339a2d..e4a8d6e 100644 (file)
@@ -17,6 +17,7 @@ import mock
 from oslo_serialization import jsonutils
 
 from yardstick.benchmark.scenarios.compute import unixbench
+from yardstick.common import exceptions as y_exc
 
 
 @mock.patch('yardstick.benchmark.scenarios.compute.unixbench.ssh')
@@ -122,7 +123,7 @@ class UnixbenchTestCase(unittest.TestCase):
         sample_output = '{"single_score":"200.7","parallel_score":"4395.9"}'
 
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, u.run, result)
+        self.assertRaises(y_exc.SLAValidationError, u.run, result)
 
     def test_unixbench_unsuccessful_sla_parallel_score(self, mock_ssh):
 
@@ -137,7 +138,7 @@ class UnixbenchTestCase(unittest.TestCase):
         sample_output = '{"signle_score":"2251.7","parallel_score":"3395.9"}'
 
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, u.run, result)
+        self.assertRaises(y_exc.SLAValidationError, u.run, result)
 
     def test_unixbench_unsuccessful_script_error(self, mock_ssh):
 
index 74144af..5f342df 100644 (file)
@@ -7,10 +7,6 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-# Unittest for yardstick.benchmark.scenarios.networking.iperf3.Iperf
-
-from __future__ import absolute_import
-
 import os
 import unittest
 
@@ -19,9 +15,10 @@ from oslo_serialization import jsonutils
 
 from yardstick.common import utils
 from yardstick.benchmark.scenarios.networking import iperf3
+from yardstick.common import exceptions as y_exc
 
 
-@mock.patch('yardstick.benchmark.scenarios.networking.iperf3.ssh')
+@mock.patch.object(iperf3, 'ssh')
 class IperfTestCase(unittest.TestCase):
     output_name_tcp = 'iperf3_sample_output.json'
     output_name_udp = 'iperf3_sample_output_udp.json'
@@ -40,9 +37,14 @@ class IperfTestCase(unittest.TestCase):
                 'ipaddr': '172.16.0.138',
             }
         }
+        self._mock_log_info = mock.patch.object(iperf3.LOG, 'info')
+        self.mock_log_info = self._mock_log_info.start()
+        self.addCleanup(self._stop_mocks)
 
-    def test_iperf_successful_setup(self, mock_ssh):
+    def _stop_mocks(self):
+        self._mock_log_info.stop()
 
+    def test_iperf_successful_setup(self, mock_ssh):
         p = iperf3.Iperf({}, self.ctx)
         mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
 
@@ -52,13 +54,11 @@ class IperfTestCase(unittest.TestCase):
         mock_ssh.SSH.from_node().execute.assert_called_with("iperf3 -s -D")
 
     def test_iperf_unsuccessful_setup(self, mock_ssh):
-
         p = iperf3.Iperf({}, self.ctx)
         mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
         self.assertRaises(RuntimeError, p.setup)
 
     def test_iperf_successful_teardown(self, mock_ssh):
-
         p = iperf3.Iperf({}, self.ctx)
         mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
         p.host = mock_ssh.SSH.from_node()
@@ -69,7 +69,6 @@ class IperfTestCase(unittest.TestCase):
         mock_ssh.SSH.from_node().execute.assert_called_with("pkill iperf3")
 
     def test_iperf_successful_no_sla(self, mock_ssh):
-
         options = {}
         args = {'options': options}
         result = {}
@@ -85,7 +84,6 @@ class IperfTestCase(unittest.TestCase):
         self.assertEqual(result, expected_result)
 
     def test_iperf_successful_sla(self, mock_ssh):
-
         options = {}
         args = {
             'options': options,
@@ -104,7 +102,6 @@ class IperfTestCase(unittest.TestCase):
         self.assertEqual(result, expected_result)
 
     def test_iperf_unsuccessful_sla(self, mock_ssh):
-
         options = {}
         args = {
             'options': options,
@@ -118,7 +115,7 @@ class IperfTestCase(unittest.TestCase):
 
         sample_output = self._read_sample_output(self.output_name_tcp)
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     def test_iperf_successful_sla_jitter(self, mock_ssh):
         options = {"protocol": "udp", "bandwidth": "20m"}
@@ -152,7 +149,7 @@ class IperfTestCase(unittest.TestCase):
 
         sample_output = self._read_sample_output(self.output_name_udp)
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     def test_iperf_successful_tcp_protocal(self, mock_ssh):
         options = {"protocol": "tcp", "nodelay": "yes"}
@@ -173,7 +170,6 @@ class IperfTestCase(unittest.TestCase):
         self.assertEqual(result, expected_result)
 
     def test_iperf_unsuccessful_script_error(self, mock_ssh):
-
         options = {}
         args = {'options': options}
         result = {}
@@ -185,7 +181,8 @@ class IperfTestCase(unittest.TestCase):
         mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
         self.assertRaises(RuntimeError, p.run, result)
 
-    def _read_sample_output(self, filename):
+    @staticmethod
+    def _read_sample_output(filename):
         curr_path = os.path.dirname(os.path.abspath(__file__))
         output = os.path.join(curr_path, filename)
         with open(output) as f:
index 5907562..a7abcd9 100755 (executable)
@@ -18,6 +18,7 @@ import mock
 from oslo_serialization import jsonutils
 
 from yardstick.benchmark.scenarios.networking import netperf
+from yardstick.common import exceptions as y_exc
 
 
 @mock.patch('yardstick.benchmark.scenarios.networking.netperf.ssh')
@@ -98,7 +99,7 @@ class NetperfTestCase(unittest.TestCase):
 
         sample_output = self._read_sample_output()
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     def test_netperf_unsuccessful_script_error(self, mock_ssh):
 
index 956a9c0..a577dba 100755 (executable)
@@ -19,6 +19,7 @@ import mock
 from oslo_serialization import jsonutils
 
 from yardstick.benchmark.scenarios.networking import netperf_node
+from yardstick.common import exceptions as y_exc
 
 
 @mock.patch('yardstick.benchmark.scenarios.networking.netperf_node.ssh')
@@ -98,7 +99,7 @@ class NetperfNodeTestCase(unittest.TestCase):
 
         sample_output = self._read_sample_output()
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     def test_netperf_node_unsuccessful_script_error(self, mock_ssh):
 
index 4adfab1..559e059 100644 (file)
@@ -14,6 +14,7 @@ import mock
 import unittest
 
 from yardstick.benchmark.scenarios.networking import ping
+from yardstick.common import exceptions as y_exc
 
 
 class PingTestCase(unittest.TestCase):
@@ -74,7 +75,7 @@ class PingTestCase(unittest.TestCase):
         p = ping.Ping(args, self.ctx)
 
         mock_ssh.SSH.from_node().execute.return_value = (0, '100', '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     @mock.patch('yardstick.benchmark.scenarios.networking.ping.ssh')
     def test_ping_unsuccessful_script_error(self, mock_ssh):
index 4662c85..ad5217a 100644 (file)
@@ -14,6 +14,7 @@ import mock
 import unittest
 
 from yardstick.benchmark.scenarios.networking import ping6
+from yardstick.common import exceptions as y_exc
 
 
 class PingTestCase(unittest.TestCase):
@@ -98,7 +99,7 @@ class PingTestCase(unittest.TestCase):
         p = ping6.Ping6(args, self.ctx)
         p.client = mock_ssh.SSH.from_node()
         mock_ssh.SSH.from_node().execute.side_effect = [(0, 'host1', ''), (0, 100, '')]
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     @mock.patch('yardstick.benchmark.scenarios.networking.ping6.ssh')
     def test_ping_unsuccessful_script_error(self, mock_ssh):
index 6aea03a..4016f50 100644 (file)
@@ -13,6 +13,7 @@ import unittest
 from oslo_serialization import jsonutils
 
 from yardstick.benchmark.scenarios.networking import pktgen
+from yardstick.common import exceptions as y_exc
 
 
 @mock.patch('yardstick.benchmark.scenarios.networking.pktgen.ssh')
@@ -55,11 +56,9 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.number_of_ports = args['options']['number_of_ports']
 
-        mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
-
         p._iptables_setup()
 
-        mock_ssh.SSH.from_node().execute.assert_called_with(
+        mock_ssh.SSH.from_node().run.assert_called_with(
             "sudo iptables -F; "
             "sudo iptables -A INPUT -p udp --dport 1000:%s -j DROP"
             % 1010, timeout=60)
@@ -74,8 +73,8 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.number_of_ports = args['options']['number_of_ports']
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
-        self.assertRaises(RuntimeError, p._iptables_setup)
+        mock_ssh.SSH.from_node().run.side_effect = y_exc.SSHError
+        self.assertRaises(y_exc.SSHError, p._iptables_setup)
 
     def test_pktgen_successful_iptables_get_result(self, mock_ssh):
 
@@ -88,12 +87,14 @@ class PktgenTestCase(unittest.TestCase):
         p.number_of_ports = args['options']['number_of_ports']
 
         mock_ssh.SSH.from_node().execute.return_value = (0, '150000', '')
-        p._iptables_get_result()
+        result = p._iptables_get_result()
+        expected_result = 150000
+        self.assertEqual(result, expected_result)
 
         mock_ssh.SSH.from_node().execute.assert_called_with(
             "sudo iptables -L INPUT -vnx |"
             "awk '/dpts:1000:%s/ {{printf \"%%s\", $1}}'"
-            % 1010)
+            % 1010, raise_on_error=True)
 
     def test_pktgen_unsuccessful_iptables_get_result(self, mock_ssh):
 
@@ -106,8 +107,8 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.number_of_ports = args['options']['number_of_ports']
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
-        self.assertRaises(RuntimeError, p._iptables_get_result)
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
+        self.assertRaises(y_exc.SSHError, p._iptables_get_result)
 
     def test_pktgen_successful_no_sla(self, mock_ssh):
 
@@ -176,7 +177,7 @@ class PktgenTestCase(unittest.TestCase):
         sample_output = '{"packets_per_second": 9753, "errors": 0, \
             "packets_sent": 149776, "packetsize": 60, "flows": 110}'
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     def test_pktgen_unsuccessful_script_error(self, mock_ssh):
 
@@ -191,8 +192,8 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.client = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
-        self.assertRaises(RuntimeError, p.run, result)
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
+        self.assertRaises(y_exc.SSHError, p.run, result)
 
     def test_pktgen_get_vnic_driver_name(self, mock_ssh):
         args = {
@@ -213,9 +214,9 @@ class PktgenTestCase(unittest.TestCase):
         p = pktgen.Pktgen(args, self.ctx)
         p.server = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._get_vnic_driver_name)
+        self.assertRaises(y_exc.SSHError, p._get_vnic_driver_name)
 
     def test_pktgen_get_sriov_queue_number(self, mock_ssh):
         args = {
@@ -236,9 +237,9 @@ class PktgenTestCase(unittest.TestCase):
         p = pktgen.Pktgen(args, self.ctx)
         p.server = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._get_sriov_queue_number)
+        self.assertRaises(y_exc.SSHError, p._get_sriov_queue_number)
 
     def test_pktgen_get_available_queue_number(self, mock_ssh):
         args = {
@@ -249,11 +250,11 @@ class PktgenTestCase(unittest.TestCase):
 
         mock_ssh.SSH.from_node().execute.return_value = (0, '4', '')
 
-        p._get_available_queue_number()
+        self.assertEqual(p._get_available_queue_number(), 4)
 
         mock_ssh.SSH.from_node().execute.assert_called_with(
             "sudo ethtool -l eth0 | grep Combined | head -1 |"
-            "awk '{printf $2}'")
+            "awk '{printf $2}'", raise_on_error=True)
 
     def test_pktgen_unsuccessful_get_available_queue_number(self, mock_ssh):
         args = {
@@ -262,9 +263,9 @@ class PktgenTestCase(unittest.TestCase):
         p = pktgen.Pktgen(args, self.ctx)
         p.server = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._get_available_queue_number)
+        self.assertRaises(y_exc.SSHError, p._get_available_queue_number)
 
     def test_pktgen_get_usable_queue_number(self, mock_ssh):
         args = {
@@ -275,11 +276,11 @@ class PktgenTestCase(unittest.TestCase):
 
         mock_ssh.SSH.from_node().execute.return_value = (0, '1', '')
 
-        p._get_usable_queue_number()
+        self.assertEqual(p._get_usable_queue_number(), 1)
 
         mock_ssh.SSH.from_node().execute.assert_called_with(
             "sudo ethtool -l eth0 | grep Combined | tail -1 |"
-            "awk '{printf $2}'")
+            "awk '{printf $2}'", raise_on_error=True)
 
     def test_pktgen_unsuccessful_get_usable_queue_number(self, mock_ssh):
         args = {
@@ -288,9 +289,9 @@ class PktgenTestCase(unittest.TestCase):
         p = pktgen.Pktgen(args, self.ctx)
         p.server = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._get_usable_queue_number)
+        self.assertRaises(y_exc.SSHError, p._get_usable_queue_number)
 
     def test_pktgen_enable_ovs_multiqueue(self, mock_ssh):
         args = {
@@ -332,12 +333,12 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.client = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().run.side_effect = y_exc.SSHError
 
         p._get_usable_queue_number = mock.Mock(return_value=1)
         p._get_available_queue_number = mock.Mock(return_value=4)
 
-        self.assertRaises(RuntimeError, p._enable_ovs_multiqueue)
+        self.assertRaises(y_exc.SSHError, p._enable_ovs_multiqueue)
 
     def test_pktgen_setup_irqmapping_ovs(self, mock_ssh):
         args = {
@@ -351,7 +352,7 @@ class PktgenTestCase(unittest.TestCase):
 
         p._setup_irqmapping_ovs(4)
 
-        mock_ssh.SSH.from_node().execute.assert_called_with(
+        mock_ssh.SSH.from_node().run.assert_called_with(
             "echo 8 | sudo tee /proc/irq/10/smp_affinity")
 
     def test_pktgen_setup_irqmapping_ovs_1q(self, mock_ssh):
@@ -366,7 +367,7 @@ class PktgenTestCase(unittest.TestCase):
 
         p._setup_irqmapping_ovs(1)
 
-        mock_ssh.SSH.from_node().execute.assert_called_with(
+        mock_ssh.SSH.from_node().run.assert_called_with(
             "echo 1 | sudo tee /proc/irq/10/smp_affinity")
 
     def test_pktgen_unsuccessful_setup_irqmapping_ovs(self, mock_ssh):
@@ -377,9 +378,9 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.client = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._setup_irqmapping_ovs, 4)
+        self.assertRaises(y_exc.SSHError, p._setup_irqmapping_ovs, 4)
 
     def test_pktgen_unsuccessful_setup_irqmapping_ovs_1q(self, mock_ssh):
         args = {
@@ -389,9 +390,9 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.client = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._setup_irqmapping_ovs, 1)
+        self.assertRaises(y_exc.SSHError, p._setup_irqmapping_ovs, 1)
 
     def test_pktgen_setup_irqmapping_sriov(self, mock_ssh):
         args = {
@@ -405,7 +406,7 @@ class PktgenTestCase(unittest.TestCase):
 
         p._setup_irqmapping_sriov(2)
 
-        mock_ssh.SSH.from_node().execute.assert_called_with(
+        mock_ssh.SSH.from_node().run.assert_called_with(
             "echo 2 | sudo tee /proc/irq/10/smp_affinity")
 
     def test_pktgen_setup_irqmapping_sriov_1q(self, mock_ssh):
@@ -420,7 +421,7 @@ class PktgenTestCase(unittest.TestCase):
 
         p._setup_irqmapping_sriov(1)
 
-        mock_ssh.SSH.from_node().execute.assert_called_with(
+        mock_ssh.SSH.from_node().run.assert_called_with(
             "echo 1 | sudo tee /proc/irq/10/smp_affinity")
 
     def test_pktgen_unsuccessful_setup_irqmapping_sriov(self, mock_ssh):
@@ -431,9 +432,9 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.client = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._setup_irqmapping_sriov, 2)
+        self.assertRaises(y_exc.SSHError, p._setup_irqmapping_sriov, 2)
 
     def test_pktgen_unsuccessful_setup_irqmapping_sriov_1q(self, mock_ssh):
         args = {
@@ -443,9 +444,9 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.client = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._setup_irqmapping_sriov, 1)
+        self.assertRaises(y_exc.SSHError, p._setup_irqmapping_sriov, 1)
 
     def test_pktgen_is_irqbalance_disabled(self, mock_ssh):
         args = {
@@ -456,10 +457,11 @@ class PktgenTestCase(unittest.TestCase):
 
         mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
 
-        p._is_irqbalance_disabled()
+        result = p._is_irqbalance_disabled()
+        self.assertFalse(result)
 
         mock_ssh.SSH.from_node().execute.assert_called_with(
-            "grep ENABLED /etc/default/irqbalance")
+            "grep ENABLED /etc/default/irqbalance", raise_on_error=True)
 
     def test_pktgen_unsuccessful_is_irqbalance_disabled(self, mock_ssh):
         args = {
@@ -468,9 +470,9 @@ class PktgenTestCase(unittest.TestCase):
         p = pktgen.Pktgen(args, self.ctx)
         p.server = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().execute.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._is_irqbalance_disabled)
+        self.assertRaises(y_exc.SSHError, p._is_irqbalance_disabled)
 
     def test_pktgen_disable_irqbalance(self, mock_ssh):
         args = {
@@ -480,11 +482,11 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.client = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+        mock_ssh.SSH.from_node().run.return_value = (0, '', '')
 
         p._disable_irqbalance()
 
-        mock_ssh.SSH.from_node().execute.assert_called_with(
+        mock_ssh.SSH.from_node().run.assert_called_with(
             "sudo service irqbalance disable")
 
     def test_pktgen_unsuccessful_disable_irqbalance(self, mock_ssh):
@@ -495,9 +497,9 @@ class PktgenTestCase(unittest.TestCase):
         p.server = mock_ssh.SSH.from_node()
         p.client = mock_ssh.SSH.from_node()
 
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        mock_ssh.SSH.from_node().run.side_effect = y_exc.SSHError
 
-        self.assertRaises(RuntimeError, p._disable_irqbalance)
+        self.assertRaises(y_exc.SSHError, p._disable_irqbalance)
 
     def test_pktgen_multiqueue_setup_ovs(self, mock_ssh):
         args = {
index 9760871..bcd4178 100644 (file)
@@ -12,6 +12,7 @@ import unittest
 
 import yardstick.common.utils as utils
 from yardstick.benchmark.scenarios.networking import pktgen_dpdk
+from yardstick.common import exceptions as y_exc
 
 
 class PktgenDPDKLatencyTestCase(unittest.TestCase):
@@ -162,9 +163,9 @@ class PktgenDPDKLatencyTestCase(unittest.TestCase):
 
         sample_output = '100\n110\n112\n130\n149\n150\n90\n150\n200\n162\n'
         self.mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
-    def test_pktgen_dpdk_unsuccessful_script_error(self):
+    def test_pktgen_dpdk_run_unsuccessful_get_port_mac(self):
 
         args = {
             'options': {'packetsize': 60},
@@ -176,3 +177,19 @@ class PktgenDPDKLatencyTestCase(unittest.TestCase):
 
         self.mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
         self.assertRaises(RuntimeError, p.run, result)
+
+    def test_pktgen_dpdk_run_unsuccessful_script_error(self):
+        args = {
+            'options': {'packetsize': 60}
+        }
+
+        p = pktgen_dpdk.PktgenDPDKLatency(args, self.ctx)
+
+        self.mock_ssh.SSH.from_node().execute.side_effect = ((0, '', ''),
+                                                             (0, '', ''),
+                                                             (0, '', ''),
+                                                             (0, '', ''),
+                                                             (0, '', ''),
+                                                             y_exc.SSHError)
+        self.assertRaises(y_exc.SSHError, p.run, {})
+        self.assertEqual(self.mock_ssh.SSH.from_node().execute.call_count, 6)
index e90fb07..39392e4 100644 (file)
@@ -16,6 +16,7 @@ from oslo_serialization import jsonutils
 import mock
 
 from yardstick.benchmark.scenarios.networking import pktgen_dpdk_throughput
+from yardstick.common import exceptions as y_exc
 
 
 # pylint: disable=unused-argument
@@ -131,7 +132,7 @@ class PktgenDPDKTestCase(unittest.TestCase):
         sample_output = '{"packets_per_second": 9753, "errors": 0, \
             "packets_sent": 149776, "flows": 110}'
         mock_ssh.SSH().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     def test_pktgen_dpdk_throughput_unsuccessful_script_error(
             self, mock_ssh):
index 2885dc6..77a54c0 100644 (file)
@@ -553,6 +553,7 @@ class TestNetworkServiceTestCase(unittest.TestCase):
             tgen.verify_traffic = lambda x: verified_dict
             tgen.terminate = mock.Mock(return_value=True)
             tgen.name = "tgen__1"
+            tgen.run_traffic.return_value = 'tg_id'
             vnf = mock.Mock(autospec=GenericVNF)
             vnf.runs_traffic = False
             vnf.terminate = mock.Mock(return_value=True)
@@ -565,7 +566,6 @@ class TestNetworkServiceTestCase(unittest.TestCase):
             self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
             self.s._fill_traffic_profile = \
                 mock.Mock(return_value=TRAFFIC_PROFILE)
-            self.assertIsNone(self.s.setup())
 
     def test_setup_exception(self):
         with mock.patch("yardstick.ssh.SSH") as ssh:
@@ -628,7 +628,8 @@ class TestNetworkServiceTestCase(unittest.TestCase):
                  'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
                  'flow': {'flow': {}},
                  'imix': {'imix': {'64B': 100}},
-                 'uplink': {}}
+                 'uplink': {},
+                 'duration': 30}
             )
             mock_tprofile_get.assert_called_once_with(fake_vnfd)
 
@@ -655,6 +656,9 @@ class TestNetworkServiceTestCase(unittest.TestCase):
         )
         self.assertEqual(self.s.topology, 'fake_nsd')
 
+    def test_get_mq_ids(self):
+        self.assertEqual(self.s._mq_ids, self.s.get_mq_ids())
+
     def test_teardown(self):
         vnf = mock.Mock(autospec=GenericVNF)
         vnf.terminate = mock.Mock(return_value=True)
index 419605b..a606543 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Unittest for yardstick.benchmark.scenarios.networking.vsperf.Vsperf
-
-from __future__ import absolute_import
-try:
-    from unittest import mock
-except ImportError:
-    import mock
+import mock
 import unittest
+import subprocess
+import yardstick.ssh as ssh
 
 from yardstick.benchmark.scenarios.networking import vsperf
+from yardstick import exceptions as y_exc
 
 
-@mock.patch('yardstick.benchmark.scenarios.networking.vsperf.subprocess')
-@mock.patch('yardstick.benchmark.scenarios.networking.vsperf.ssh')
 class VsperfTestCase(unittest.TestCase):
 
     def setUp(self):
-        self.ctx = {
+        self.context_cfg = {
             "host": {
                 "ip": "10.229.47.137",
                 "user": "ubuntu",
                 "password": "ubuntu",
             },
         }
-        self.args = {
+        self.scenario_cfg = {
             'options': {
                 'testname': 'p2p_rfc2544_continuous',
                 'traffic_type': 'continuous',
@@ -57,70 +52,154 @@ class VsperfTestCase(unittest.TestCase):
             }
         }
 
-    def test_vsperf_setup(self, mock_ssh, mock_subprocess):
-        p = vsperf.Vsperf(self.args, self.ctx)
-        mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
-        mock_subprocess.call().execute.return_value = None
+        self._mock_SSH = mock.patch.object(ssh, 'SSH')
+        self.mock_SSH = self._mock_SSH.start()
+        self.mock_SSH.from_node().execute.return_value = (0, '', '')
+
+        self._mock_subprocess_call = mock.patch.object(subprocess, 'call')
+        self.mock_subprocess_call = self._mock_subprocess_call.start()
+        self.mock_subprocess_call.return_value = None
+
+        self.addCleanup(self._stop_mock)
+
+        self.scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+
+    def _stop_mock(self):
+        self._mock_SSH.stop()
+        self._mock_subprocess_call.stop()
+
+    def test_setup(self):
+        self.scenario.setup()
+        self.assertIsNotNone(self.scenario.client)
+        self.assertTrue(self.scenario.setup_done)
+
+    def test_setup_tg_port_not_set(self):
+        del self.scenario_cfg['options']['trafficgen_port1']
+        del self.scenario_cfg['options']['trafficgen_port2']
+        scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+        scenario.setup()
+
+        self.mock_subprocess_call.assert_called_once_with(
+            'setup_yardstick.sh setup', shell=True)
+        self.assertIsNone(scenario.tg_port1)
+        self.assertIsNone(scenario.tg_port2)
+        self.assertIsNotNone(scenario.client)
+        self.assertTrue(scenario.setup_done)
+
+    def test_setup_no_setup_script(self):
+        del self.scenario_cfg['options']['setup_script']
+        scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+        scenario.setup()
+
+        self.mock_subprocess_call.assert_has_calls(
+            (mock.call('sudo bash -c "ovs-vsctl add-port br-ex eth1"',
+                       shell=True),
+             mock.call('sudo bash -c "ovs-vsctl add-port br-ex eth3"',
+                       shell=True)))
+        self.assertEqual(2, self.mock_subprocess_call.call_count)
+        self.assertIsNone(scenario.setup_script)
+        self.assertIsNotNone(scenario.client)
+        self.assertTrue(scenario.setup_done)
+
+    def test_run_ok(self):
+        self.scenario.setup()
+
+        self.mock_SSH.from_node().execute.return_value = (
+            0, 'throughput_rx_fps\r\n14797660.000\r\n', '')
 
-        p.setup()
-        self.assertIsNotNone(p.client)
-        self.assertTrue(p.setup_done)
+        result = {}
+        self.scenario.run(result)
 
-    def test_vsperf_teardown(self, mock_ssh, mock_subprocess):
-        p = vsperf.Vsperf(self.args, self.ctx)
+        self.assertEqual(result['throughput_rx_fps'], '14797660.000')
 
-        # setup() specific mocks
-        mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
-        mock_subprocess.call().execute.return_value = None
+    def test_run_ok_setup_not_done(self):
+        self.mock_SSH.from_node().execute.return_value = (
+            0, 'throughput_rx_fps\r\n14797660.000\r\n', '')
 
-        p.setup()
-        self.assertIsNotNone(p.client)
-        self.assertTrue(p.setup_done)
+        result = {}
+        self.scenario.run(result)
 
-        p.teardown()
-        self.assertFalse(p.setup_done)
+        self.assertTrue(self.scenario.setup_done)
+        self.assertEqual(result['throughput_rx_fps'], '14797660.000')
 
-    def test_vsperf_run_ok(self, mock_ssh, mock_subprocess):
-        p = vsperf.Vsperf(self.args, self.ctx)
+    def test_run_failed_vsperf_execution(self):
+        self.mock_SSH.from_node().execute.side_effect = ((0, '', ''),
+                                                         (1, '', ''))
 
-        # setup() specific mocks
-        mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
-        mock_subprocess.call().execute.return_value = None
+        with self.assertRaises(RuntimeError):
+            self.scenario.run({})
+        self.assertEqual(self.mock_SSH.from_node().execute.call_count, 2)
 
-        # run() specific mocks
-        mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
-        mock_ssh.SSH.from_node().execute.return_value = (
-            0, 'throughput_rx_fps\r\n14797660.000\r\n', '')
+    def test_run_failed_csv_report(self):
+        self.mock_SSH.from_node().execute.side_effect = ((0, '', ''),
+                                                         (0, '', ''),
+                                                         (1, '', ''))
 
-        result = {}
-        p.run(result)
+        with self.assertRaises(RuntimeError):
+            self.scenario.run({})
+        self.assertEqual(self.mock_SSH.from_node().execute.call_count, 3)
 
-        self.assertEqual(result['throughput_rx_fps'], '14797660.000')
+    def test_run_sla_fail(self):
+        self.mock_SSH.from_node().execute.return_value = (
+            0, 'throughput_rx_fps\r\n123456.000\r\n', '')
 
-    def test_vsperf_run_falied_vsperf_execution(self, mock_ssh,
-                                                mock_subprocess):
-        p = vsperf.Vsperf(self.args, self.ctx)
+        with self.assertRaises(y_exc.SLAValidationError) as raised:
+            self.scenario.run({})
 
-        # setup() specific mocks
-        mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
-        mock_subprocess.call().execute.return_value = None
+        self.assertTrue('VSPERF_throughput_rx_fps(123456.000000) < '
+                        'SLA_throughput_rx_fps(500000.000000)'
+                        in str(raised.exception))
 
-        # run() specific mocks
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+    def test_run_sla_fail_metric_not_collected(self):
+        self.mock_SSH.from_node().execute.return_value = (
+            0, 'nonexisting_metric\r\n14797660.000\r\n', '')
 
-        result = {}
-        self.assertRaises(RuntimeError, p.run, result)
+        with self.assertRaises(y_exc.SLAValidationError) as raised:
+            self.scenario.run({})
 
-    def test_vsperf_run_falied_csv_report(self, mock_ssh, mock_subprocess):
-        p = vsperf.Vsperf(self.args, self.ctx)
+        self.assertTrue('throughput_rx_fps was not collected by VSPERF'
+                        in str(raised.exception))
 
-        # setup() specific mocks
-        mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
-        mock_subprocess.call().execute.return_value = None
+    def test_run_sla_fail_metric_not_defined_in_sla(self):
+        del self.scenario_cfg['sla']['throughput_rx_fps']
+        scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+        scenario.setup()
 
-        # run() specific mocks
-        mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
-        mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+        self.mock_SSH.from_node().execute.return_value = (
+            0, 'throughput_rx_fps\r\n14797660.000\r\n', '')
 
-        result = {}
-        self.assertRaises(RuntimeError, p.run, result)
+        with self.assertRaises(y_exc.SLAValidationError) as raised:
+            scenario.run({})
+        self.assertTrue('throughput_rx_fps is not defined in SLA'
+                        in str(raised.exception))
+
+    def test_teardown(self):
+        self.scenario.setup()
+        self.assertIsNotNone(self.scenario.client)
+        self.assertTrue(self.scenario.setup_done)
+
+        self.scenario.teardown()
+        self.assertFalse(self.scenario.setup_done)
+
+    def test_teardown_tg_port_not_set(self):
+        del self.scenario_cfg['options']['trafficgen_port1']
+        del self.scenario_cfg['options']['trafficgen_port2']
+        scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+        scenario.teardown()
+
+        self.mock_subprocess_call.assert_called_once_with(
+            'setup_yardstick.sh teardown', shell=True)
+        self.assertFalse(scenario.setup_done)
+
+    def test_teardown_no_setup_script(self):
+        del self.scenario_cfg['options']['setup_script']
+        scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+        scenario.teardown()
+
+        self.mock_subprocess_call.assert_has_calls(
+            (mock.call('sudo bash -c "ovs-vsctl del-port br-ex eth1"',
+                       shell=True),
+             mock.call('sudo bash -c "ovs-vsctl del-port br-ex eth3"',
+                       shell=True)))
+        self.assertEqual(2, self.mock_subprocess_call.call_count)
+        self.assertFalse(scenario.setup_done)
index 1d2278e..db6f9cc 100644 (file)
@@ -18,6 +18,7 @@ import time
 import mock
 import unittest
 
+from yardstick import exceptions as y_exc
 from yardstick.benchmark.scenarios.networking import vsperf_dpdk
 
 
@@ -58,17 +59,18 @@ class VsperfDPDKTestCase(unittest.TestCase):
 
         self.scenario = vsperf_dpdk.VsperfDPDK(self.args, self.ctx)
 
-        self._mock_ssh = mock.patch(
-            'yardstick.benchmark.scenarios.networking.vsperf_dpdk.ssh')
+        self._mock_ssh = mock.patch.object(vsperf_dpdk, 'ssh')
         self.mock_ssh = self._mock_ssh.start()
         self._mock_subprocess_call = mock.patch.object(subprocess, 'call')
         self.mock_subprocess_call = self._mock_subprocess_call.start()
-
+        self._mock_log_info = mock.patch.object(vsperf_dpdk.LOG, 'info')
+        self.mock_log_info = self._mock_log_info.start()
         self.addCleanup(self._cleanup)
 
     def _cleanup(self):
         self._mock_ssh.stop()
         self._mock_subprocess_call.stop()
+        self._mock_log_info.stop()
 
     def test_setup(self):
         # setup() specific mocks
@@ -211,3 +213,47 @@ class VsperfDPDKTestCase(unittest.TestCase):
 
         result = {}
         self.assertRaises(RuntimeError, self.scenario.run, result)
+
+    @mock.patch.object(time, 'sleep')
+    @mock.patch.object(subprocess, 'check_output')
+    def test_vsperf_run_sla_fail(self, *args):
+        self.scenario.setup()
+
+        self.mock_ssh.SSH.from_node().execute.return_value = (
+            0, 'throughput_rx_fps\r\n123456.000\r\n', '')
+
+        with self.assertRaises(y_exc.SLAValidationError) as raised:
+            self.scenario.run({})
+
+        self.assertIn('VSPERF_throughput_rx_fps(123456.000000) < '
+                      'SLA_throughput_rx_fps(500000.000000)',
+                      str(raised.exception))
+
+    @mock.patch.object(time, 'sleep')
+    @mock.patch.object(subprocess, 'check_output')
+    def test_vsperf_run_sla_fail_metric_not_collected(self, *args):
+        self.scenario.setup()
+
+        self.mock_ssh.SSH.from_node().execute.return_value = (
+            0, 'nonexisting_metric\r\n123456.000\r\n', '')
+
+        with self.assertRaises(y_exc.SLAValidationError) as raised:
+            self.scenario.run({})
+
+        self.assertIn('throughput_rx_fps was not collected by VSPERF',
+                      str(raised.exception))
+
+    @mock.patch.object(time, 'sleep')
+    @mock.patch.object(subprocess, 'check_output')
+    def test_vsperf_run_sla_fail_sla_not_defined(self, *args):
+        del self.scenario.scenario_cfg['sla']['throughput_rx_fps']
+        self.scenario.setup()
+
+        self.mock_ssh.SSH.from_node().execute.return_value = (
+            0, 'throughput_rx_fps\r\n14797660.000\r\n', '')
+
+        with self.assertRaises(y_exc.SLAValidationError) as raised:
+            self.scenario.run({})
+
+        self.assertIn('throughput_rx_fps is not defined in SLA',
+                      str(raised.exception))
index f149cee..6e69ddc 100644 (file)
@@ -18,6 +18,7 @@ import mock
 from oslo_serialization import jsonutils
 
 from yardstick.benchmark.scenarios.storage import fio
+from yardstick.common import exceptions as y_exc
 
 
 @mock.patch('yardstick.benchmark.scenarios.storage.fio.ssh')
@@ -203,7 +204,7 @@ class FioTestCase(unittest.TestCase):
 
         sample_output = self._read_sample_output(self.sample_output['rw'])
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     def test_fio_successful_bw_iops_sla(self, mock_ssh):
 
@@ -252,7 +253,7 @@ class FioTestCase(unittest.TestCase):
 
         sample_output = self._read_sample_output(self.sample_output['rw'])
         mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
-        self.assertRaises(AssertionError, p.run, result)
+        self.assertRaises(y_exc.SLAValidationError, p.run, result)
 
     def test_fio_unsuccessful_script_error(self, mock_ssh):
 
index 00ec220..37b1f19 100644 (file)
@@ -44,3 +44,39 @@ class PayloadTestCase(ut_base.BaseUnitTestCase):
         _dict = {'version': 2, 'key1': 'value100', 'key2': 'value200'}
         payload = _DummyPayload.dict_to_obj(_dict)
         self.assertEqual(set(_dict.keys()), payload._fields)
+
+
+class TrafficGeneratorPayloadTestCase(ut_base.BaseUnitTestCase):
+
+    def test_init(self):
+        tg_payload = payloads.TrafficGeneratorPayload(
+            version=1, iteration=10, kpi={'key1': 'value1'})
+        self.assertEqual(1, tg_payload.version)
+        self.assertEqual(10, tg_payload.iteration)
+        self.assertEqual({'key1': 'value1'}, tg_payload.kpi)
+        self.assertEqual(3, len(tg_payload._fields))
+
+    def test__init_missing_required_fields(self):
+        with self.assertRaises(exceptions.PayloadMissingAttributes):
+            payloads.TrafficGeneratorPayload(version=1, iteration=10)
+        with self.assertRaises(exceptions.PayloadMissingAttributes):
+            payloads.TrafficGeneratorPayload(iteration=10, kpi={})
+        with self.assertRaises(exceptions.PayloadMissingAttributes):
+            payloads.TrafficGeneratorPayload(iteration=10)
+
+
+class RunnerPayloadTestCase(ut_base.BaseUnitTestCase):
+
+    def test_init(self):
+        runner_payload = payloads.RunnerPayload(version=5,
+                                                data={'key1': 'value1'})
+        self.assertEqual(5, runner_payload.version)
+        self.assertEqual({'key1': 'value1'}, runner_payload.data)
+
+    def test__init_missing_required_fields(self):
+        with self.assertRaises(exceptions.PayloadMissingAttributes):
+            payloads.RunnerPayload(version=1)
+        with self.assertRaises(exceptions.PayloadMissingAttributes):
+            payloads.RunnerPayload(data=None)
+        with self.assertRaises(exceptions.PayloadMissingAttributes):
+            payloads.RunnerPayload()
index 0289689..22286e5 100644 (file)
@@ -44,3 +44,10 @@ class MessagingProducerTestCase(ut_base.BaseUnitTestCase):
                 topic='test_topic', fanout=True, server=messaging.SERVER)
             mock_RPCClient.assert_called_once_with('test_rpc_transport',
                                                    'test_Target')
+
+    def test_id(self):
+        with mock.patch.object(oslo_messaging, 'RPCClient'), \
+                mock.patch.object(oslo_messaging, 'get_rpc_transport'), \
+                mock.patch.object(oslo_messaging, 'Target'):
+            msg_producer = _MessagingProducer('topic', 'id_to_check')
+        self.assertEqual('id_to_check', msg_producer.id)
index 9361a97..f6a0bdc 100644 (file)
@@ -7,11 +7,13 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-from oslo_utils import uuidutils
-import unittest
+import os
+
 import mock
+from oslo_utils import uuidutils
 import shade
 from shade import exc
+import unittest
 
 from yardstick.common import constants
 from yardstick.common import openstack_utils
@@ -28,11 +30,12 @@ class GetCredentialsTestCase(unittest.TestCase):
 
 class GetHeatApiVersionTestCase(unittest.TestCase):
 
-    def test_get_heat_api_version_check_result(self):
+    @mock.patch.object(openstack_utils, 'log')
+    def test_get_heat_api_version_check_result(self, *args):
         API = 'HEAT_API_VERSION'
         expected_result = '2'
 
-        with mock.patch.dict('os.environ', {API: '2'}, clear=True):
+        with mock.patch.dict(os.environ, {API: '2'}, clear=True):
             api_version = openstack_utils.get_heat_api_version()
             self.assertEqual(api_version, expected_result)
 
@@ -59,6 +62,12 @@ class GetShadeClientTestCase(unittest.TestCase):
         mock_openstack_cloud.assert_called_once_with(
             **constants.OS_CLOUD_DEFAULT_CONFIG)
 
+    @mock.patch.object(shade, 'operator_cloud', return_value='os_client')
+    def test_get_shade_operator_client(self, mock_operator_cloud):
+        self.assertEqual('os_client', openstack_utils.get_shade_operator_client())
+        mock_operator_cloud.assert_called_once_with(
+            **constants.OS_CLOUD_DEFAULT_CONFIG)
+
 
 class DeleteNeutronNetTestCase(unittest.TestCase):
 
@@ -271,6 +280,12 @@ class CreateSecurityGroupRuleTestCase(unittest.TestCase):
         self.mock_shade_client = mock.Mock()
         self.secgroup_name_or_id = 'sg_name_id'
         self.mock_shade_client.create_security_group_rule = mock.Mock()
+        self._mock_log = mock.patch.object(openstack_utils, 'log')
+        self.mock_log = self._mock_log.start()
+        self.addCleanup(self._stop_mock)
+
+    def _stop_mock(self):
+        self._mock_log.stop()
 
     def test_create_security_group_rule(self):
         self.mock_shade_client.create_security_group_rule.return_value = (
@@ -279,14 +294,13 @@ class CreateSecurityGroupRuleTestCase(unittest.TestCase):
             self.mock_shade_client, self.secgroup_name_or_id)
         self.assertTrue(output)
 
-    @mock.patch.object(openstack_utils, 'log')
-    def test_create_security_group_rule_exception(self, mock_logger):
+    def test_create_security_group_rule_exception(self):
         self.mock_shade_client.create_security_group_rule.side_effect = (
             exc.OpenStackCloudException('error message'))
 
         output = openstack_utils.create_security_group_rule(
             self.mock_shade_client, self.secgroup_name_or_id)
-        mock_logger.error.assert_called_once()
+        self.mock_log.error.assert_called_once()
         self.assertFalse(output)
 
 
@@ -315,6 +329,12 @@ class SecurityGroupTestCase(unittest.TestCase):
         self.sg_name = 'sg_name'
         self.sg_description = 'sg_description'
         self._uuid = uuidutils.generate_uuid()
+        self._mock_log = mock.patch.object(openstack_utils, 'log')
+        self.mock_log = self._mock_log.start()
+        self.addCleanup(self._stop_mock)
+
+    def _stop_mock(self):
+        self._mock_log.stop()
 
     def test_create_security_group_full_existing_security_group(self):
         self.mock_shade_client.get_security_group.return_value = (
@@ -324,21 +344,18 @@ class SecurityGroupTestCase(unittest.TestCase):
         self.mock_shade_client.get_security_group.assert_called_once()
         self.assertEqual(self._uuid, output)
 
-    @mock.patch.object(openstack_utils, 'log')
-    def test_create_security_group_full_non_existing_security_group(
-            self, mock_logger):
+    def test_create_security_group_full_non_existing_security_group(self):
         self.mock_shade_client.get_security_group.return_value = None
         self.mock_shade_client.create_security_group.side_effect = (
             exc.OpenStackCloudException('error message'))
         output = openstack_utils.create_security_group_full(
             self.mock_shade_client, self.sg_name, self.sg_description)
-        mock_logger.error.assert_called_once()
+        self.mock_log.error.assert_called_once()
         self.assertIsNone(output)
 
     @mock.patch.object(openstack_utils, 'create_security_group_rule')
-    @mock.patch.object(openstack_utils, 'log')
     def test_create_security_group_full_create_rule_fail(
-            self, mock_logger, mock_create_security_group_rule):
+            self, mock_create_security_group_rule):
         self.mock_shade_client.get_security_group.return_value = None
         self.mock_shade_client.create_security_group.return_value = (
             {'name': 'name', 'id': self._uuid})
@@ -347,7 +364,7 @@ class SecurityGroupTestCase(unittest.TestCase):
             self.mock_shade_client, self.sg_name, self.sg_description)
         mock_create_security_group_rule.assert_called()
         self.mock_shade_client.delete_security_group(self.sg_name)
-        mock_logger.error.assert_called_once()
+        self.mock_log.error.assert_called_once()
         self.assertIsNone(output)
 
     @mock.patch.object(openstack_utils, 'create_security_group_rule')
@@ -363,10 +380,6 @@ class SecurityGroupTestCase(unittest.TestCase):
         self.mock_shade_client.delete_security_group(self.sg_name)
         self.assertEqual(self._uuid, output)
 
-# *********************************************
-#   NOVA
-# *********************************************
-
 
 class CreateInstanceTestCase(unittest.TestCase):
 
@@ -537,10 +550,6 @@ class GetFlavorTestCase(unittest.TestCase):
         mock_logger.error.assert_called_once()
         self.assertIsNone(output)
 
-# *********************************************
-#   CINDER
-# *********************************************
-
 
 class GetVolumeIDTestCase(unittest.TestCase):
 
@@ -658,22 +667,23 @@ class DetachVolumeTestCase(unittest.TestCase):
         self.assertFalse(output)
 
 
-# *********************************************
-#   GLANCE
-# *********************************************
-
 class CreateImageTestCase(unittest.TestCase):
 
     def setUp(self):
         self.mock_shade_client = mock.Mock()
         self._uuid = uuidutils.generate_uuid()
         self.name = 'image_name'
+        self._mock_log = mock.patch.object(openstack_utils, 'log')
+        self.mock_log = self._mock_log.start()
+        self.addCleanup(self._stop_mock)
 
-    @mock.patch.object(openstack_utils, 'log')
-    def test_create_image_already_exit(self, mock_logger):
+    def _stop_mock(self):
+        self._mock_log.stop()
+
+    def test_create_image_already_exit(self):
         self.mock_shade_client.get_image_id.return_value = self._uuid
         output = openstack_utils.create_image(self.mock_shade_client, self.name)
-        mock_logger.info.assert_called_once()
+        self.mock_log.info.assert_called_once()
         self.assertEqual(self._uuid, output)
 
     def test_create_image(self):
@@ -682,15 +692,14 @@ class CreateImageTestCase(unittest.TestCase):
         output = openstack_utils.create_image(self.mock_shade_client, self.name)
         self.assertEqual(self._uuid, output)
 
-    @mock.patch.object(openstack_utils, 'log')
-    def test_create_image_exception(self, mock_logger):
+    def test_create_image_exception(self):
         self.mock_shade_client.get_image_id.return_value = None
         self.mock_shade_client.create_image.side_effect = (
             exc.OpenStackCloudException('error message'))
 
         output = openstack_utils.create_image(self.mock_shade_client,
                                               self.name)
-        mock_logger.error.assert_called_once()
+        self.mock_log.error.assert_called_once()
         self.assertIsNone(output)
 
 
index 1c6dfec..e0933c6 100644 (file)
@@ -90,10 +90,11 @@ class ExecuteTestCase(unittest.TestCase):
             additional_env=self.additional_env)
         self.assertEqual(self.stdout, out)
 
-    def test_execute_exception(self):
+    @mock.patch.object(process, 'LOG')
+    def test_execute_exception(self, *args):
         self.obj.returncode = self.RET_CODE_WRONG
-        self.assertRaises(exceptions.ProcessExecutionError, process.execute,
-                          self.input_cmd, additional_env=self.additional_env)
+        with self.assertRaises(exceptions.ProcessExecutionError):
+            process.execute(self.input_cmd, additional_env=self.additional_env)
         self.obj.communicate.assert_called_once_with(None)
 
     def test_execute_with_extra_code(self):
@@ -107,7 +108,8 @@ class ExecuteTestCase(unittest.TestCase):
             additional_env=self.additional_env)
         self.assertEqual(self.stdout, out)
 
-    def test_execute_exception_no_check(self):
+    @mock.patch.object(process, 'LOG')
+    def test_execute_exception_no_check(self, *args):
         self.obj.returncode = self.RET_CODE_WRONG
         out = process.execute(self.input_cmd,
                               additional_env=self.additional_env,
index 10ad0a6..446afdd 100644 (file)
@@ -25,9 +25,10 @@ from yardstick import ssh
 from yardstick.common import constants
 from yardstick.common import utils
 from yardstick.common import exceptions
+from yardstick.tests.unit import base as ut_base
 
 
-class IterSubclassesTestCase(unittest.TestCase):
+class IterSubclassesTestCase(ut_base.BaseUnitTestCase):
     # Disclaimer: this class is a modified copy from
     # rally/tests/unit/common/plugin/test_discover.py
     # Copyright 2015: Mirantis Inc.
@@ -48,7 +49,7 @@ class IterSubclassesTestCase(unittest.TestCase):
         self.assertEqual([B, C, D], list(utils.itersubclasses(A)))
 
 
-class ImportModulesFromPackageTestCase(unittest.TestCase):
+class ImportModulesFromPackageTestCase(ut_base.BaseUnitTestCase):
 
     @mock.patch('yardstick.common.utils.os.walk')
     def test_import_modules_from_package_no_mod(self, mock_walk):
@@ -73,7 +74,7 @@ class ImportModulesFromPackageTestCase(unittest.TestCase):
         mock_import_module.assert_called_once_with('bar.baz')
 
 
-class GetParaFromYaml(unittest.TestCase):
+class GetParaFromYaml(ut_base.BaseUnitTestCase):
 
     @mock.patch('yardstick.common.utils.os.environ.get')
     def test_get_param_para_not_found(self, get_env):
@@ -97,7 +98,7 @@ class GetParaFromYaml(unittest.TestCase):
         return file_path
 
 
-class CommonUtilTestCase(unittest.TestCase):
+class CommonUtilTestCase(ut_base.BaseUnitTestCase):
 
     def setUp(self):
         self.data = {
@@ -187,14 +188,14 @@ class CommonUtilTestCase(unittest.TestCase):
         self.assertEqual(mock_open.call_count, mock_open_call_count)
 
 
-class TestMacAddressToHex(unittest.TestCase):
+class TestMacAddressToHex(ut_base.BaseUnitTestCase):
 
     def test_mac_address_to_hex_list(self):
         self.assertEqual(utils.mac_address_to_hex_list("ea:3e:e1:9a:99:e8"),
                          ['0xea', '0x3e', '0xe1', '0x9a', '0x99', '0xe8'])
 
 
-class TranslateToStrTestCase(unittest.TestCase):
+class TranslateToStrTestCase(ut_base.BaseUnitTestCase):
 
     def test_translate_to_str_unicode(self):
         input_str = u'hello'
@@ -220,7 +221,7 @@ class TranslateToStrTestCase(unittest.TestCase):
         self.assertIs(input_value, result)
 
 
-class TestParseCpuInfo(unittest.TestCase):
+class TestParseCpuInfo(ut_base.BaseUnitTestCase):
 
     def test_single_socket_no_hyperthread(self):
         cpuinfo = """\
@@ -805,7 +806,7 @@ power management:
         self.assertEqual(sockets, [0, 1])
 
 
-class ChangeObjToDictTestCase(unittest.TestCase):
+class ChangeObjToDictTestCase(ut_base.BaseUnitTestCase):
 
     def test_change_obj_to_dict(self):
         class A(object):
@@ -818,7 +819,7 @@ class ChangeObjToDictTestCase(unittest.TestCase):
         self.assertEqual(obj_r, obj_s)
 
 
-class SetDictValueTestCase(unittest.TestCase):
+class SetDictValueTestCase(ut_base.BaseUnitTestCase):
 
     def test_set_dict_value(self):
         input_dic = {
@@ -828,7 +829,7 @@ class SetDictValueTestCase(unittest.TestCase):
         self.assertEqual(output_dic.get('welcome', {}).get('to'), 'yardstick')
 
 
-class RemoveFileTestCase(unittest.TestCase):
+class RemoveFileTestCase(ut_base.BaseUnitTestCase):
 
     def test_remove_file(self):
         try:
@@ -838,7 +839,83 @@ class RemoveFileTestCase(unittest.TestCase):
             self.assertTrue(isinstance(e, OSError))
 
 
-class TestUtils(unittest.TestCase):
+class ParseIniFileTestCase(ut_base.BaseUnitTestCase):
+
+    def setUp(self):
+        self._mock_config_parser_type = mock.patch.object(configparser,
+                                                          'ConfigParser')
+        self.mock_config_parser_type = self._mock_config_parser_type.start()
+        self.addCleanup(self._stop_mocks)
+
+    def _stop_mocks(self):
+        self._mock_config_parser_type.stop()
+
+    def test_parse_ini_file(self):
+        defaults = {'default1': 'value1',
+                    'default2': 'value2'}
+        s1 = {'key1': 'value11',
+              'key2': 'value22'}
+        s2 = {'key1': 'value123',
+              'key2': 'value234'}
+
+        mock_config_parser = mock.Mock()
+        self.mock_config_parser_type.return_value = mock_config_parser
+        mock_config_parser.read.return_value = True
+        mock_config_parser.sections.return_value = ['s1', 's2']
+        mock_config_parser.items.side_effect = iter([
+            defaults.items(),
+            s1.items(),
+            s2.items(),
+        ])
+
+        expected = {'DEFAULT': defaults,
+                    's1': s1,
+                    's2': s2}
+        result = utils.parse_ini_file('my_path')
+        self.assertDictEqual(expected, result)
+
+    @mock.patch.object(utils, 'logger')
+    def test_parse_ini_file_missing_section_header(self, *args):
+        mock_config_parser = mock.Mock()
+        self.mock_config_parser_type.return_value = mock_config_parser
+        mock_config_parser.read.side_effect = (
+            configparser.MissingSectionHeaderError(
+                mock.Mock(), 321, mock.Mock()))
+
+        with self.assertRaises(configparser.MissingSectionHeaderError):
+            utils.parse_ini_file('my_path')
+
+    def test_parse_ini_file_no_file(self):
+        mock_config_parser = mock.Mock()
+        self.mock_config_parser_type.return_value = mock_config_parser
+        mock_config_parser.read.return_value = False
+        with self.assertRaises(RuntimeError):
+            utils.parse_ini_file('my_path')
+
+    def test_parse_ini_file_no_default_section_header(self):
+        s1 = {'key1': 'value11',
+              'key2': 'value22'}
+        s2 = {'key1': 'value123',
+              'key2': 'value234'}
+
+        mock_config_parser = mock.Mock()
+        self.mock_config_parser_type.return_value = mock_config_parser
+        mock_config_parser.read.return_value = True
+        mock_config_parser.sections.return_value = ['s1', 's2']
+        mock_config_parser.items.side_effect = iter([
+            configparser.NoSectionError(mock.Mock()),
+            s1.items(),
+            s2.items(),
+        ])
+
+        expected = {'DEFAULT': {},
+                    's1': s1,
+                    's2': s2}
+        result = utils.parse_ini_file('my_path')
+        self.assertDictEqual(expected, result)
+
+
+class TestUtils(ut_base.BaseUnitTestCase):
 
     @mock.patch('yardstick.common.utils.os.makedirs')
     def test_makedirs(self, *_):
@@ -993,7 +1070,7 @@ class TestUtils(unittest.TestCase):
             utils.validate_non_string_sequence(1, raise_exc=RuntimeError)
 
 
-class TestUtilsIpAddrMethods(unittest.TestCase):
+class TestUtilsIpAddrMethods(ut_base.BaseUnitTestCase):
 
     GOOD_IP_V4_ADDRESS_STR_LIST = [
         u'0.0.0.0',
@@ -1120,7 +1197,7 @@ class TestUtilsIpAddrMethods(unittest.TestCase):
             self.assertEqual(utils.ip_to_hex(value), value)
 
 
-class SafeDecodeUtf8TestCase(unittest.TestCase):
+class SafeDecodeUtf8TestCase(ut_base.BaseUnitTestCase):
 
     @unittest.skipIf(six.PY2,
                      'This test should only be launched with Python 3.x')
@@ -1131,7 +1208,7 @@ class SafeDecodeUtf8TestCase(unittest.TestCase):
         self.assertEqual('this is a byte array', out)
 
 
-class ReadMeminfoTestCase(unittest.TestCase):
+class ReadMeminfoTestCase(ut_base.BaseUnitTestCase):
 
     MEMINFO = (b'MemTotal:       65860500 kB\n'
                b'MemFree:        28690900 kB\n'
@@ -1157,7 +1234,7 @@ class ReadMeminfoTestCase(unittest.TestCase):
         self.assertEqual(self.MEMINFO_DICT, output)
 
 
-class TimerTestCase(unittest.TestCase):
+class TimerTestCase(ut_base.BaseUnitTestCase):
 
     def test__getattr(self):
         with utils.Timer() as timer:
@@ -1175,8 +1252,19 @@ class TimerTestCase(unittest.TestCase):
             with utils.Timer(timeout=1):
                 time.sleep(2)
 
+    def test__enter_with_timeout_no_exception(self):
+        with utils.Timer(timeout=1, raise_exception=False):
+            time.sleep(2)
+
+    def test__iter(self):
+        iterations = []
+        for i in utils.Timer(timeout=2):
+            iterations.append(i)
+            time.sleep(1.1)
+        self.assertEqual(2, len(iterations))
+
 
-class WaitUntilTrueTestCase(unittest.TestCase):
+class WaitUntilTrueTestCase(ut_base.BaseUnitTestCase):
 
     def test_no_timeout(self):
         self.assertIsNone(utils.wait_until_true(lambda: True,
index 14e26f7..4271f85 100644 (file)
@@ -38,6 +38,15 @@ class MockVnfAprrox(object):
 
 class CollectorTestCase(unittest.TestCase):
 
+    NODES = {'context1': [{'name': 'node1',
+                           'ip': '1.2.3.4',
+                           'collectd': {
+                               'plugins': {'abc': 12, 'def': 34},
+                               'interval': 987
+                           },
+                           }]
+             }
+
     def setUp(self):
         vnf = MockVnfAprrox()
         vnf.start_collect = mock.Mock()
@@ -47,30 +56,46 @@ class CollectorTestCase(unittest.TestCase):
         mock_instance = mock.Mock()
         mock_instance.execute.return_value = 0, '', ''
         mock_ssh.from_node.return_value = mock_instance
-        self.collector = subscriber.Collector([vnf])
+        self.collector = subscriber.Collector([vnf], self.NODES)
 
     def tearDown(self):
         self.ssh_patch.stop()
 
     def test___init__(self, *_):
         vnf = MockVnfAprrox()
-        collector = subscriber.Collector([vnf])
+        collector = subscriber.Collector([vnf], self.NODES)
         self.assertEqual(len(collector.vnfs), 1)
+        self.assertEqual(len(collector.nodes), 1)
 
     def test_start(self, *_):
+        resource_profile = mock.MagicMock()
+        self.collector.resource_profiles = {'key': resource_profile}
+        self.collector.bin_path = 'path'
+
         self.assertIsNone(self.collector.start())
         for vnf in self.collector.vnfs:
             vnf.start_collect.assert_called_once()
 
+        for resource_profile in self.collector.resource_profiles.values():
+            resource_profile.initiate_systemagent.assert_called_once_with('path')
+            resource_profile.start.assert_called_once()
+            resource_profile.amqp_process_for_nfvi_kpi.assert_called_once()
+
     def test_stop(self, *_):
+        resource_profile = mock.MagicMock()
+        self.collector.resource_profiles = {'key': resource_profile}
+
         self.assertIsNone(self.collector.stop())
         for vnf in self.collector.vnfs:
             vnf.stop_collect.assert_called_once()
 
+        for resource in self.collector.resource_profiles.values():
+            resource.stop.assert_called_once()
+
     def test_get_kpi(self, *_):
         result = self.collector.get_kpi()
 
-        self.assertEqual(1, len(result))
+        self.assertEqual(2, len(result))
         self.assertEqual(4, len(result["vnf__1"]))
         self.assertEqual(result["vnf__1"]["pkt_in_up_stream"], 100)
         self.assertEqual(result["vnf__1"]["pkt_drop_up_stream"], 5)
index 9d94e3d..e193116 100644 (file)
@@ -289,7 +289,7 @@ class TestDpdkNode(unittest.TestCase):
         dpdk_helper.force_dpdk_rebind = mock_helper_func = mock.Mock()
 
         dpdk_node._force_rebind()
-        self.assertEqual(mock_helper_func.call_count, 1)
+        mock_helper_func.assert_called_once()
 
 
 class TestDpdkBindHelper(unittest.TestCase):
index 6d5e1da..e66e7fb 100644 (file)
@@ -223,7 +223,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'arp_route_tbl': '', 'arp_route_tbl6': '',
-                                    'rules': ''})
+                                    'flows': ''})
         opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         self.assertIsNotNone(opnfv_vnf.generate_script(self.VNFD))
         opnfv_vnf.lb_config = 'HW'
@@ -249,66 +249,6 @@ class TestMultiPortConfig(unittest.TestCase):
         opnfv_vnf.generate_rule_config = mock.Mock()
         self.assertIsNotNone(opnfv_vnf.generate_script_data())
 
-    def test_generate_rule_config(self):
-        topology_file = mock.Mock()
-        config_tpl = mock.Mock()
-        tmp_file = mock.Mock()
-        vnfd_mock = mock.MagicMock()
-        opnfv_vnf = samplevnf_helper.MultiPortConfig(
-            topology_file, config_tpl, tmp_file, vnfd_mock)
-        opnfv_vnf.get_config_tpl_data = mock.MagicMock()
-        opnfv_vnf.socket = 0
-        opnfv_vnf.start_core = 0
-        opnfv_vnf.update_write_parser = mock.MagicMock()
-        opnfv_vnf.generate_script_data = \
-            mock.Mock(return_value={'link_config': 0, 'arp_config': '',
-                                    'arp_config6': '', 'actions': '',
-                                    'rules': ''})
-        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
-        opnfv_vnf.get_port_pairs = mock.Mock()
-        opnfv_vnf.vnf_type = 'ACL'
-        opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
-        opnfv_vnf.get_netmask_gateway = mock.Mock(
-            return_value=u'255.255.255.0')
-        opnfv_vnf.get_ports_gateway6 = mock.Mock(return_value=u'1.1.1.1')
-        opnfv_vnf.get_netmask_gateway6 = mock.Mock(
-            return_value=u'255.255.255.0')
-        opnfv_vnf.txrx_pipeline = ''
-        opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
-        opnfv_vnf.rules = ''
-        self.assertIsNotNone(opnfv_vnf.generate_rule_config())
-        opnfv_vnf.rules = 'new'
-        self.assertIsNotNone(opnfv_vnf.generate_rule_config())
-
-    def test_generate_action_config(self):
-        topology_file = mock.Mock()
-        config_tpl = mock.Mock()
-        tmp_file = mock.Mock()
-        vnfd_mock = mock.MagicMock()
-        opnfv_vnf = samplevnf_helper.MultiPortConfig(
-            topology_file, config_tpl, tmp_file, vnfd_mock)
-        opnfv_vnf.get_config_tpl_data = mock.MagicMock()
-        opnfv_vnf.socket = 0
-        opnfv_vnf.start_core = 0
-        opnfv_vnf.update_write_parser = mock.MagicMock()
-        opnfv_vnf.generate_script_data = \
-            mock.Mock(return_value={'link_config': 0, 'arp_config': '',
-                                    'arp_config6': '', 'actions': '',
-                                    'rules': ''})
-        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
-        opnfv_vnf.get_port_pairs = mock.Mock()
-        opnfv_vnf.vnf_type = 'VFW'
-        opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
-        opnfv_vnf.get_netmask_gateway = mock.Mock(
-            return_value=u'255.255.255.0')
-        opnfv_vnf.get_ports_gateway6 = mock.Mock(return_value=u'1.1.1.1')
-        opnfv_vnf.get_netmask_gateway6 = mock.Mock(
-            return_value=u'255.255.255.0')
-        opnfv_vnf.txrx_pipeline = ''
-        opnfv_vnf.rules = ''
-        self.assertIsNotNone(opnfv_vnf.generate_action_config())
-
     def test_generate_arp_config6(self):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
index 34afa3d..541855a 100644 (file)
@@ -203,13 +203,9 @@ class TestIxNextgen(unittest.TestCase):
         ixnet_gen._ixnet = self.ixnet
         framesize = {'64B': '75', '512b': '25'}
         output = ixnet_gen._parse_framesize(framesize)
-        for idx in range(len(framesize)):
-            if output[idx * 2] == 64:
-                self.assertEqual(75, output[idx * 2 + 1])
-            elif output[idx * 2] == 512:
-                self.assertEqual(25, output[idx * 2 + 1])
-            else:
-                raise self.failureException('Framesize (64, 512) not present')
+        self.assertEqual(2, len(output))
+        self.assertIn([64, 64, 75], output)
+        self.assertIn([512, 512, 25], output)
 
     @mock.patch.object(IxNetwork, 'IxNet')
     def test_connect(self, mock_ixnet):
index de96794..c066582 100644 (file)
@@ -18,6 +18,7 @@ import mock
 import unittest
 
 from yardstick.common import exceptions
+from yardstick.common.exceptions import ResourceCommandError
 from yardstick.network_services.nfvi.resource import ResourceProfile
 from yardstick.network_services.nfvi import resource, collectd
 
@@ -139,18 +140,38 @@ class TestResourceProfile(unittest.TestCase):
             self.resource_profile._start_collectd(ssh_mock, "/opt/nsb_bin")
 
         ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
-        self.assertIsNone(self.resource_profile._start_collectd(ssh_mock,
-                                                                "/opt/nsb_bin"))
+        with self.assertRaises(ResourceCommandError):
+            self.resource_profile._start_collectd(ssh_mock, "/opt/nsb_bin")
+
+    def test__reset_rabbitmq(self):
+        ssh_mock = mock.Mock()
+        ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
+        with self.assertRaises(exceptions.ResourceCommandError):
+            self.resource_profile._reset_rabbitmq(ssh_mock)
+
+    def test__check_rabbitmq_user(self):
+        ssh_mock = mock.Mock()
+        ssh_mock.execute = mock.Mock(return_value=(0, "title\nadmin\t[]", ""))
+        self.assertTrue(self.resource_profile._check_rabbitmq_user(ssh_mock))
+
+    def test__set_rabbitmq_admin_user(self):
+        ssh_mock = mock.Mock()
+        ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
+        with self.assertRaises(exceptions.ResourceCommandError):
+            self.resource_profile._set_rabbitmq_admin_user(ssh_mock)
 
     def test__start_rabbitmq(self):
         ssh_mock = mock.Mock()
-        ssh_mock.execute = mock.Mock(return_value=(0, "RabbitMQ", ""))
-        self.assertIsNone(self.resource_profile._start_rabbitmq(ssh_mock))
+        self.resource_profile._reset_rabbitmq = mock.Mock()
+        self.resource_profile._set_rabbitmq_admin_user = mock.Mock()
 
-        ssh_mock.execute = mock.Mock(return_value=(0, "", ""))
+        self.resource_profile._reset_mq_flag = True
+        ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
         with self.assertRaises(exceptions.ResourceCommandError):
             self.resource_profile._start_rabbitmq(ssh_mock)
 
+        self.resource_profile._reset_mq_flag = False
+        self.resource_profile._check_rabbitmq_user = mock.Mock(return_value=False)
         ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
         with self.assertRaises(exceptions.ResourceCommandError):
             self.resource_profile._start_rabbitmq(ssh_mock)
diff --git a/yardstick/tests/unit/network_services/test_yang_model.py b/yardstick/tests/unit/network_services/test_yang_model.py
deleted file mode 100644 (file)
index a7eb36b..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright (c) 2016-2017 Intel Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# 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.
-#
-
-import mock
-import unittest
-
-from yardstick.network_services.yang_model import YangModel
-
-
-class YangModelTestCase(unittest.TestCase):
-    """Test all Yang Model methods."""
-
-    ENTRIES = {
-        'access-list1': {
-            'acl': {
-                'access-list-entries': [{
-                    'ace': {
-                        'ace-oper-data': {
-                            'match-counter': 0},
-                        'actions': 'drop,count',
-                        'matches': {
-                            'destination-ipv4-network':
-                                '152.16.40.20/24',
-                            'destination-port-range': {
-                                'lower-port': 0,
-                                'upper-port': 65535},
-                            'source-ipv4-network': '0.0.0.0/0',
-                            'source-port-range': {
-                                'lower-port': 0,
-                                'upper-port': 65535}},
-                        'rule-name': 'rule1588'}},
-                    {
-                        'ace': {
-                            'ace-oper-data': {
-                                'match-counter': 0},
-                            'actions': 'drop,count',
-                            'matches': {
-                                'destination-ipv4-network':
-                                    '0.0.0.0/0',
-                                'destination-port-range': {
-                                    'lower-port': 0,
-                                    'upper-port': 65535},
-                                'source-ipv4-network':
-                                    '152.16.100.20/24',
-                                'source-port-range': {
-                                    'lower-port': 0,
-                                    'upper-port': 65535}},
-                            'rule-name': 'rule1589'}}],
-                'acl-name': 'sample-ipv4-acl',
-                    'acl-type': 'ipv4-acl'}
-        }
-    }
-
-    def test__init__(self):
-        cfg = "yang.yaml"
-        y = YangModel(cfg)
-        self.assertEqual(y.config_file, cfg)
-
-    def test_config_file_setter(self):
-        cfg = "yang.yaml"
-        y = YangModel(cfg)
-        self.assertEqual(y.config_file, cfg)
-        cfg2 = "yang2.yaml"
-        y.config_file = cfg2
-        self.assertEqual(y.config_file, cfg2)
-
-    def test__get_entries(self):
-        cfg = "yang.yaml"
-        y = YangModel(cfg)
-        y._options = self.ENTRIES
-        y._get_entries()
-        self.assertIn("p acl add", y._rules)
-
-    def test__get_entries_no_options(self):
-        cfg = "yang.yaml"
-        y = YangModel(cfg)
-        y._get_entries()
-        self.assertEqual(y._rules, '')
-
-    @mock.patch('yardstick.network_services.yang_model.open')
-    @mock.patch('yardstick.network_services.yang_model.yaml_load')
-    def test__read_config(self, mock_safe_load, *args):
-        cfg = "yang.yaml"
-        y = YangModel(cfg)
-        mock_safe_load.return_value = expected = {'key1': 'value1', 'key2': 'value2'}
-        y._read_config()
-        self.assertDictEqual(y._options, expected)
-
-    @mock.patch('yardstick.network_services.yang_model.open')
-    def test__read_config_open_error(self, mock_open):
-        cfg = "yang.yaml"
-        y = YangModel(cfg)
-        mock_open.side_effect = IOError('my error')
-
-        self.assertEqual(y._options, {})
-        with self.assertRaises(IOError) as raised:
-            y._read_config()
-
-        self.assertIn('my error', str(raised.exception))
-        self.assertEqual(y._options, {})
-
-    def test_get_rules(self):
-        cfg = "yang.yaml"
-        y = YangModel(cfg)
-        y._read_config = read_mock = mock.Mock()
-        y._get_entries = get_mock = mock.Mock()
-
-        y._rules = None
-        self.assertIsNone(y.get_rules())
-        self.assertEqual(read_mock.call_count, 1)
-        self.assertEqual(get_mock.call_count, 1)
-
-        # True value should prevent calling read and get
-        y._rules = 999
-        self.assertEqual(y.get_rules(), 999)
-        self.assertEqual(read_mock.call_count, 1)
-        self.assertEqual(get_mock.call_count, 1)
index 641064c..55276af 100644 (file)
@@ -69,5 +69,20 @@ class TestTrafficProfile(unittest.TestCase):
 
 class TestDummyProfile(unittest.TestCase):
     def test_execute(self):
-        dummy_profile = base.DummyProfile(base.TrafficProfile)
+        tp_config = {'traffic_profile': {'duration': 15}}
+        dummy_profile = base.DummyProfile(tp_config)
         self.assertIsNone(dummy_profile.execute({}))
+
+
+class TrafficProfileConfigTestCase(unittest.TestCase):
+
+    def test__init(self):
+        tp_config = {'traffic_profile': {'packet_sizes': {'64B': 100}}}
+        tp_config_obj = base.TrafficProfileConfig(tp_config)
+        self.assertEqual({'64B': 100}, tp_config_obj.packet_sizes)
+        self.assertEqual(base.TrafficProfileConfig.DEFAULT_SCHEMA,
+                         tp_config_obj.schema)
+        self.assertEqual(base.TrafficProfileConfig.DEFAULT_FRAME_RATE,
+                         tp_config_obj.frame_rate)
+        self.assertEqual(base.TrafficProfileConfig.DEFAULT_DURATION,
+                         tp_config_obj.duration)
index 39905e6..2f67137 100644 (file)
@@ -102,8 +102,7 @@ class TestFixedProfile(unittest.TestCase):
                'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
 
     def test___init__(self):
-        fixed_profile = \
-            FixedProfile(TrafficProfile)
+        fixed_profile = FixedProfile(self.TRAFFIC_PROFILE)
         self.assertIsNotNone(fixed_profile)
 
     def test_execute(self):
index 0d1b916..d44fab2 100644 (file)
 # 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.
-#
 
 import unittest
 
-from yardstick.network_services.traffic_profile.base import TrafficProfile
-from yardstick.network_services.traffic_profile.http import \
-    TrafficProfileGenericHTTP
+from yardstick.network_services.traffic_profile import http
 
 
 class TestTrafficProfileGenericHTTP(unittest.TestCase):
+
+    TP_CONFIG = {'traffic_profile': {'duration': 10}}
+
     def test___init__(self):
-        traffic_profile_generic_htt_p = \
-            TrafficProfileGenericHTTP(TrafficProfile)
-        self.assertIsNotNone(traffic_profile_generic_htt_p)
+        tp_generic_http = http.TrafficProfileGenericHTTP(
+            self.TP_CONFIG)
+        self.assertIsNotNone(tp_generic_http)
 
     def test_execute(self):
-        traffic_profile_generic_htt_p = \
-            TrafficProfileGenericHTTP(TrafficProfile)
+        tp_generic_http = http.TrafficProfileGenericHTTP(
+            self.TP_CONFIG)
         traffic_generator = {}
-        self.assertIsNone(
-            traffic_profile_generic_htt_p.execute(traffic_generator))
+        self.assertIsNone(tp_generic_http.execute(traffic_generator))
 
     def test__send_http_request(self):
-        traffic_profile_generic_htt_p = \
-                TrafficProfileGenericHTTP(TrafficProfile)
-        self.assertIsNone(traffic_profile_generic_htt_p._send_http_request(
-                             "10.1.1.1", "250", "/req"))
+        tp_generic_http = http.TrafficProfileGenericHTTP(
+            self.TP_CONFIG)
+        self.assertIsNone(tp_generic_http._send_http_request(
+            '10.1.1.1', '250', '/req'))
index 6b3532f..3bb8b91 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from copy import deepcopy
+import copy
 
 import mock
 import unittest
@@ -440,6 +440,12 @@ class TestIXIARFC2544Profile(unittest.TestCase):
         result = r_f_c2544_profile._get_ixia_traffic_profile(profile_data, mac)
         self.assertIsNotNone(result)
 
+    def test__init__(self):
+        t_profile_data = copy.deepcopy(self.TRAFFIC_PROFILE)
+        t_profile_data['traffic_profile']['frame_rate'] = 12345678
+        r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(t_profile_data)
+        self.assertEqual(12345678, r_f_c2544_profile.rate)
+
     def test__get_ixia_traffic_profile_default_args(self):
         r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
             self.TRAFFIC_PROFILE)
@@ -521,7 +527,7 @@ class TestIXIARFC2544Profile(unittest.TestCase):
         traffic_generator.vnfd_helper.port_num.side_effect = ports_expected
         traffic_generator.client.return_value = True
 
-        traffic_profile = deepcopy(self.TRAFFIC_PROFILE)
+        traffic_profile = copy.deepcopy(self.TRAFFIC_PROFILE)
         traffic_profile.update({
             "uplink_0": ["xe0"],
             "downlink_0": ["xe1", "xe2"],
index 7bfd67f..c062308 100644 (file)
 # 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.
-#
 
 import unittest
 import mock
 
-from yardstick.tests import STL_MOCKS
+from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxTestDataTuple
+from yardstick.network_services.traffic_profile import prox_binsearch
 
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
 
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxTestDataTuple
-    from yardstick.network_services.traffic_profile.prox_binsearch import ProxBinSearchProfile
+class TestProxBinSearchProfile(unittest.TestCase):
 
+    def setUp(self):
+        self._mock_log_info = mock.patch.object(prox_binsearch.LOG, 'info')
+        self.mock_log_info = self._mock_log_info.start()
+        self.addCleanup(self._stop_mocks)
 
-class TestProxBinSearchProfile(unittest.TestCase):
+    def _stop_mocks(self):
+        self._mock_log_info.stop()
 
     def test_execute_1(self):
         def target(*args, **_):
@@ -51,22 +51,28 @@ class TestProxBinSearchProfile(unittest.TestCase):
         fail_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.6, 5.7, 5.8], 850, 1000, 123.4)
 
         traffic_generator = mock.MagicMock()
+        attrs1 = {'get.return_value' : 10}
+        traffic_generator.scenario_helper.all_options.configure_mock(**attrs1)
+
+        attrs2 = {'__getitem__.return_value' : 10, 'get.return_value': 10}
+        traffic_generator.scenario_helper.scenario_cfg["runner"].configure_mock(**attrs2)
 
         profile_helper = mock.MagicMock()
         profile_helper.run_test = target
 
-        profile = ProxBinSearchProfile(tp_config)
+        profile = prox_binsearch.ProxBinSearchProfile(tp_config)
         profile.init(mock.MagicMock())
         profile._profile_helper = profile_helper
 
         profile.execute_traffic(traffic_generator)
+
         self.assertEqual(round(profile.current_lower, 2), 74.69)
         self.assertEqual(round(profile.current_upper, 2), 76.09)
-        self.assertEqual(len(runs), 7)
+        self.assertEqual(len(runs), 77)
 
         # Result Samples inc theor_max
         result_tuple = {'Result_Actual_throughput': 5e-07,
-                        'Result_theor_max_throughput': 0.00012340000000000002,
+                        'Result_theor_max_throughput': 7.5e-07,
                         'Result_pktSize': 200}
 
         profile.queue.put.assert_called_with(result_tuple)
@@ -123,11 +129,16 @@ class TestProxBinSearchProfile(unittest.TestCase):
         fail_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.6, 5.7, 5.8], 850, 1000, 123.4)
 
         traffic_generator = mock.MagicMock()
+        attrs1 = {'get.return_value': 10}
+        traffic_generator.scenario_helper.all_options.configure_mock(**attrs1)
+
+        attrs2 = {'__getitem__.return_value': 0, 'get.return_value': 0}
+        traffic_generator.scenario_helper.scenario_cfg["runner"].configure_mock(**attrs2)
 
         profile_helper = mock.MagicMock()
         profile_helper.run_test = target
 
-        profile = ProxBinSearchProfile(tp_config)
+        profile = prox_binsearch.ProxBinSearchProfile(tp_config)
         profile.init(mock.MagicMock())
         profile._profile_helper = profile_helper
 
@@ -162,7 +173,7 @@ class TestProxBinSearchProfile(unittest.TestCase):
         profile_helper = mock.MagicMock()
         profile_helper.run_test = target
 
-        profile = ProxBinSearchProfile(tp_config)
+        profile = prox_binsearch.ProxBinSearchProfile(tp_config)
         profile.init(mock.MagicMock())
         profile._profile_helper = profile_helper
 
@@ -172,7 +183,8 @@ class TestProxBinSearchProfile(unittest.TestCase):
 
 
         # Result Samples
-        result_tuple = {"Result_theor_max_throughput": 0, "Result_pktSize": 200}
+        result_tuple = {'Result_Actual_throughput': 0, "Result_theor_max_throughput": 0,
+                        "Result_pktSize": 200}
         profile.queue.put.assert_called_with(result_tuple)
 
         # Check for success_ tuple (None expected)
@@ -182,3 +194,81 @@ class TestProxBinSearchProfile(unittest.TestCase):
                 for k in call_detail:
                     if "Success_" in k:
                         self.assertRaises(AttributeError)
+
+    def test_execute_4(self):
+
+        def target(*args, **_):
+            runs.append(args[2])
+            if args[2] < 0 or args[2] > 100:
+                raise RuntimeError(' '.join([str(args), str(runs)]))
+            if args[2] > 75.0:
+                return fail_tuple, {}
+            return success_tuple, {}
+
+        tp_config = {
+            'traffic_profile': {
+                'packet_sizes': [200],
+                'test_precision': 2.0,
+                'tolerated_loss': 0.001,
+            },
+        }
+
+        runs = []
+        success_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.1, 5.2, 5.3], 995, 1000, 123.4)
+        fail_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.6, 5.7, 5.8], 850, 1000, 123.4)
+
+        traffic_generator = mock.MagicMock()
+        attrs1 = {'get.return_value': 100000}
+        traffic_generator.scenario_helper.all_options.configure_mock(**attrs1)
+
+        attrs2 = {'__getitem__.return_value': 0, 'get.return_value': 0}
+        traffic_generator.scenario_helper.scenario_cfg["runner"].configure_mock(**attrs2)
+
+        profile_helper = mock.MagicMock()
+        profile_helper.run_test = target
+
+        profile = prox_binsearch.ProxBinSearchProfile(tp_config)
+        profile.init(mock.MagicMock())
+        profile._profile_helper = profile_helper
+
+        profile.execute_traffic(traffic_generator)
+        self.assertEqual(round(profile.current_lower, 2), 74.69)
+        self.assertEqual(round(profile.current_upper, 2), 76.09)
+        self.assertEqual(len(runs), 7)
+
+        # Result Samples inc theor_max
+        result_tuple = {'Result_Actual_throughput': 5e-07,
+                        'Result_theor_max_throughput': 7.5e-07,
+                        'Result_pktSize': 200}
+
+        profile.queue.put.assert_called_with(result_tuple)
+
+        success_result_tuple = {"Success_CurrentDropPackets": 0.5,
+                                "Success_DropPackets": 0.5,
+                                "Success_LatencyAvg": 5.3,
+                                "Success_LatencyMax": 5.2,
+                                "Success_LatencyMin": 5.1,
+                                "Success_PktSize": 200,
+                                "Success_RxThroughput": 7.5e-07,
+                                "Success_Throughput": 7.5e-07,
+                                "Success_TxThroughput": 0.00012340000000000002}
+
+        calls = profile.queue.put(success_result_tuple)
+        profile.queue.put.assert_has_calls(calls)
+
+        success_result_tuple2 = {"Success_CurrentDropPackets": 0.5,
+                                 "Success_DropPackets": 0.5,
+                                 "Success_LatencyAvg": 5.3,
+                                 "Success_LatencyMax": 5.2,
+                                 "Success_LatencyMin": 5.1,
+                                 "Success_PktSize": 200,
+                                 "Success_RxThroughput": 7.5e-07,
+                                 "Success_Throughput": 7.5e-07,
+                                 "Success_TxThroughput": 123.4,
+                                 "Success_can_be_lost": 409600,
+                                 "Success_drop_total": 20480,
+                                 "Success_rx_total": 4075520,
+                                 "Success_tx_total": 4096000}
+
+        calls = profile.queue.put(success_result_tuple2)
+        profile.queue.put.assert_has_calls(calls)
index e466305..cf31cc2 100644 (file)
@@ -124,5 +124,5 @@ class TestProxProfile(unittest.TestCase):
         for _ in profile.bounds_iterator(mock_logger):
             pass
 
-        self.assertEqual(mock_logger.debug.call_count, 1)
+        mock_logger.debug.assert_called_once()
         self.assertEqual(mock_logger.info.call_count, 10)
index 2684e0b..0cf93f9 100644 (file)
 # 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.
-#
 
-import unittest
 import mock
 
-from yardstick.tests import STL_MOCKS
-
+from trex_stl_lib import api as Pkt
+from trex_stl_lib import trex_stl_client
+from trex_stl_lib import trex_stl_packet_builder_scapy
+from trex_stl_lib import trex_stl_streams
 
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
+from yardstick.network_services.traffic_profile import rfc2544
+from yardstick.tests.unit import base
 
-if stl_patch:
-    from yardstick.network_services.traffic_profile.trex_traffic_profile \
-        import TrexProfile
-    from yardstick.network_services.traffic_profile.rfc2544 import \
-        RFC2544Profile
 
-
-class TestRFC2544Profile(unittest.TestCase):
+class TestRFC2544Profile(base.BaseUnitTestCase):
     TRAFFIC_PROFILE = {
         "schema": "isb:traffic_profile:0.1",
         "name": "fixed",
         "description": "Fixed traffic profile to run UDP traffic",
         "traffic_profile": {
             "traffic_type": "FixedTraffic",
-            "frame_rate": 100,  # pps
+            "frame_rate": 100,
             "flow_number": 10,
             "frame_size": 64}}
 
@@ -45,233 +38,251 @@ class TestRFC2544Profile(unittest.TestCase):
                'name': 'rfc2544',
                'traffic_profile': {'traffic_type': 'RFC2544Profile',
                                    'frame_rate': 100},
-               'downlink_0': {'ipv4':
-                              {'outer_l2': {'framesize':
-                                            {'64B': '100', '1518B': '0',
-                                             '128B': '0', '1400B': '0',
-                                             '256B': '0', '373b': '0',
-                                             '570B': '0'}},
-                               'outer_l3v4': {'dstip4': '1.1.1.1-1.15.255.255',
-                                              'proto': 'udp',
-                                              'srcip4': '90.90.1.1-90.105.255.255',
-                                              'dscp': 0, 'ttl': 32, 'count': 1},
-                               'outer_l4': {'srcport': '2001',
-                                            'dsrport': '1234', 'count': 1}}},
-               'uplink_0': {'ipv4':
-                            {'outer_l2': {'framesize':
-                                          {'64B': '100', '1518B': '0',
-                                           '128B': '0', '1400B': '0',
-                                           '256B': '0', '373b': '0',
-                                           '570B': '0'}},
-                             'outer_l3v4': {'dstip4': '9.9.1.1-90.105.255.255',
-                                            'proto': 'udp',
-                                            'srcip4': '1.1.1.1-1.15.255.255',
-                                            'dscp': 0, 'ttl': 32, 'count': 1},
-                             'outer_l4': {'dstport': '2001',
-                                          'srcport': '1234', 'count': 1}}},
+               'downlink_0':
+                   {'ipv4':
+                        {'outer_l2':
+                             {'framesize':
+                                  {'64B': '100', '1518B': '0',
+                                   '128B': '0', '1400B': '0',
+                                   '256B': '0', '373b': '0',
+                                   '570B': '0'}},
+                         'outer_l3v4':
+                             {'dstip4': '1.1.1.1-1.15.255.255',
+                              'proto': 'udp',
+                              'srcip4': '90.90.1.1-90.105.255.255',
+                              'dscp': 0, 'ttl': 32, 'count': 1},
+                         'outer_l4':
+                             {'srcport': '2001',
+                              'dsrport': '1234', 'count': 1}}},
+               'uplink_0':
+                   {'ipv4':
+                        {'outer_l2':
+                             {'framesize':
+                                  {'64B': '100', '1518B': '0',
+                                   '128B': '0', '1400B': '0',
+                                   '256B': '0', '373b': '0',
+                                   '570B': '0'}},
+                         'outer_l3v4':
+                             {'dstip4': '9.9.1.1-90.105.255.255',
+                              'proto': 'udp',
+                              'srcip4': '1.1.1.1-1.15.255.255',
+                              'dscp': 0, 'ttl': 32, 'count': 1},
+                         'outer_l4':
+                             {'dstport': '2001',
+                              'srcport': '1234', 'count': 1}}},
                'schema': 'isb:traffic_profile:0.1'}
 
     def test___init__(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        self.assertIsNotNone(r_f_c2544_profile.rate)
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        self.assertEqual(rfc2544_profile.max_rate, rfc2544_profile.rate)
+        self.assertEqual(0, rfc2544_profile.min_rate)
 
-    def test_execute(self):
-        traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.networks = {
-            "uplink_0": ["xe0"],
-            "downlink_0": ["xe1"],
-        }
-        traffic_generator.client.return_value = True
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        r_f_c2544_profile.first_run = True
-        self.assertIsNone(r_f_c2544_profile.execute_traffic(traffic_generator))
+    def test_stop_traffic(self):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        mock_generator = mock.Mock()
+        rfc2544_profile.stop_traffic(traffic_generator=mock_generator)
+        mock_generator.client.stop.assert_called_once()
+        mock_generator.client.reset.assert_called_once()
+        mock_generator.client.remove_all_streams.assert_called_once()
 
-    def test_get_drop_percentage(self):
-        traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.networks = {
-            "uplink_0": ["xe0"],
-            "downlink_0": ["xe1"],
-        }
-        traffic_generator.client.return_value = True
+    def test_execute_traffic(self):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        mock_generator = mock.Mock()
+        mock_generator.networks = {
+            'downlink_0': ['xe0', 'xe1'],
+            'uplink_0': ['xe2', 'xe3'],
+            'downlink_1': []}
+        mock_generator.port_num.side_effect = [10, 20, 30, 40]
+        mock_generator.rfc2544_helper.correlated_traffic = False
+        rfc2544_profile.params = {
+            'downlink_0': 'profile1',
+            'uplink_0': 'profile2'}
 
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        r_f_c2544_profile.register_generator(traffic_generator)
-        self.assertIsNone(r_f_c2544_profile.execute_traffic(traffic_generator))
+        with mock.patch.object(rfc2544_profile, '_create_profile') as \
+                mock_create_profile:
+            rfc2544_profile.execute_traffic(traffic_generator=mock_generator)
+        mock_create_profile.assert_has_calls([
+            mock.call('profile1', rfc2544_profile.rate, mock.ANY),
+            mock.call('profile1', rfc2544_profile.rate, mock.ANY),
+            mock.call('profile2', rfc2544_profile.rate, mock.ANY),
+            mock.call('profile2', rfc2544_profile.rate, mock.ANY)])
+        mock_generator.client.add_streams.assert_has_calls([
+            mock.call(mock.ANY, ports=[10]),
+            mock.call(mock.ANY, ports=[20]),
+            mock.call(mock.ANY, ports=[30]),
+            mock.call(mock.ANY, ports=[40])])
+        mock_generator.client.start(ports=[10, 20, 30, 40],
+                                    duration=rfc2544_profile.config.duration,
+                                    force=True)
 
-        samples = {}
-        for ifname in range(1):
-            name = "xe{}".format(ifname)
-            samples[name] = {
-                "rx_throughput_fps": 20,
-                "tx_throughput_fps": 20,
-                "rx_throughput_mbps": 10,
-                "tx_throughput_mbps": 10,
-                "in_packets": 1000,
-                "out_packets": 1000,
-            }
+    @mock.patch.object(trex_stl_streams, 'STLProfile')
+    def test__create_profile(self, mock_stl_profile):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        port_pg_id = mock.ANY
+        profile_data = {'packetid_1': {'outer_l2': {'framesize': 'imix_info'}}}
+        rate = 100
+        with mock.patch.object(rfc2544_profile, '_create_imix_data') as \
+                mock_create_imix, \
+                mock.patch.object(rfc2544_profile, '_create_vm') as \
+                mock_create_vm, \
+                mock.patch.object(rfc2544_profile, '_create_streams') as \
+                mock_create_streams:
+            mock_create_imix.return_value = 'imix_data'
+            mock_create_streams.return_value = ['stream1']
+            rfc2544_profile._create_profile(profile_data, rate, port_pg_id)
 
-        expected = {
-            'DropPercentage': 0.0,
-            'RxThroughput': 100 / 3.0,
-            'TxThroughput': 100 / 3.0,
-            'CurrentDropPercentage': 0.0,
-            'Throughput': 66.66666666666667,
-            'xe0': {
-                'tx_throughput_fps': 20,
-                'in_packets': 1000,
-                'out_packets': 1000,
-                'rx_throughput_mbps': 10,
-                'tx_throughput_mbps': 10,
-                'rx_throughput_fps': 20,
-            },
-        }
-        traffic_generator.generate_samples.return_value = samples
-        traffic_generator.RUN_DURATION = 30
-        traffic_generator.rfc2544_helper.tolerance_low = 0.0001
-        traffic_generator.rfc2544_helper.tolerance_high = 0.0001
-        result = r_f_c2544_profile.get_drop_percentage(traffic_generator)
-        self.assertDictEqual(result, expected)
+        mock_create_imix.assert_called_once_with('imix_info')
+        mock_create_vm.assert_called_once_with(
+            {'outer_l2': {'framesize': 'imix_info'}})
+        mock_create_streams.assert_called_once_with('imix_data', 100,
+                                                    port_pg_id)
+        mock_stl_profile.assert_called_once_with(['stream1'])
 
-    def test_get_drop_percentage_update(self):
-        traffic_generator = mock.Mock(autospec=RFC2544Profile)
-        traffic_generator.networks = {
-            "uplink_0": ["xe0"],
-            "downlink_0": ["xe1"],
-        }
-        traffic_generator.client = mock.Mock(return_value=True)
+    def test__create_imix_data(self):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        data = {'64B': 50, '128B': 50}
+        self.assertEqual({'64': 50.0, '128': 50.0},
+                         rfc2544_profile._create_imix_data(data))
+        data = {'64B': 1, '128b': 3}
+        self.assertEqual({'64': 25.0, '128': 75.0},
+                         rfc2544_profile._create_imix_data(data))
+        data = {}
+        self.assertEqual({}, rfc2544_profile._create_imix_data(data))
 
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        r_f_c2544_profile.register_generator(traffic_generator)
-        self.assertIsNone(r_f_c2544_profile.execute_traffic())
+    def test__create_vm(self):
+        packet = {'outer_l2': 'l2_definition'}
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        with mock.patch.object(rfc2544_profile, '_set_outer_l2_fields') as \
+                mock_l2_fileds:
+            rfc2544_profile._create_vm(packet)
+        mock_l2_fileds.assert_called_once_with('l2_definition')
 
-        samples = {}
-        for ifname in range(1):
-            name = "xe{}".format(ifname)
-            samples[name] = {
-                "rx_throughput_fps": 20,
-                "tx_throughput_fps": 20,
-                "rx_throughput_mbps": 10,
-                "tx_throughput_mbps": 10,
-                "in_packets": 1000,
-                "out_packets": 1002,
-            }
-        expected = {
-            'DropPercentage': 0.1996,
-            'RxThroughput': 33.333333333333336,
-            'TxThroughput': 33.4,
-            'CurrentDropPercentage': 0.1996,
-            'Throughput': 66.66666666666667,
-            'xe0': {
-                'tx_throughput_fps': 20,
-                'in_packets': 1000,
-                'out_packets': 1002,
-                'rx_throughput_mbps': 10,
-                'tx_throughput_mbps': 10,
-                'rx_throughput_fps': 20,
-            },
-        }
-        traffic_generator.generate_samples = mock.MagicMock(
-            return_value=samples)
-        traffic_generator.RUN_DURATION = 30
-        traffic_generator.rfc2544_helper.tolerance_low = 0.0001
-        traffic_generator.rfc2544_helper.tolerance_high = 0.0001
-        result = r_f_c2544_profile.get_drop_percentage(traffic_generator)
-        self.assertDictEqual(expected, result)
+    @mock.patch.object(trex_stl_packet_builder_scapy, 'STLPktBuilder',
+                       return_value='packet')
+    def test__create_single_packet(self, mock_pktbuilder):
+        size = 128
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        rfc2544_profile.ether_packet = Pkt.Eth()
+        rfc2544_profile.ip_packet = Pkt.IP()
+        rfc2544_profile.udp_packet = Pkt.UDP()
+        rfc2544_profile.trex_vm = 'trex_vm'
+        base_pkt = (rfc2544_profile.ether_packet / rfc2544_profile.ip_packet /
+                    rfc2544_profile.udp_packet)
+        pad = (size - len(base_pkt)) * 'x'
+        output = rfc2544_profile._create_single_packet(size=size)
+        mock_pktbuilder.assert_called_once_with(pkt=base_pkt / pad,
+                                                vm='trex_vm')
+        self.assertEqual(output, 'packet')
 
-    def test_get_drop_percentage_div_zero(self):
-        traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.networks = {
-            "uplink_0": ["xe0"],
-            "downlink_0": ["xe1"],
-        }
-        traffic_generator.client = \
-            mock.Mock(return_value=True)
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        self.assertIsNone(
-            r_f_c2544_profile.execute_traffic(traffic_generator))
-        samples = {}
-        for ifname in range(1):
-            name = "xe{}".format(ifname)
-            samples[name] = {"rx_throughput_fps": 20,
-                             "tx_throughput_fps": 20,
-                             "rx_throughput_mbps": 10,
-                             "tx_throughput_mbps": 10,
-                             "in_packets": 1000,
-                             "out_packets": 0}
-        r_f_c2544_profile.throughput_max = 0
-        expected = {
-            'DropPercentage': 100.0, 'RxThroughput': 100 / 3.0,
-            'TxThroughput': 0.0, 'CurrentDropPercentage': 100.0,
-            'Throughput': 66.66666666666667,
-            'xe0': {
-                'tx_throughput_fps': 20, 'in_packets': 1000,
-                'out_packets': 0, 'rx_throughput_mbps': 10,
-                'tx_throughput_mbps': 10, 'rx_throughput_fps': 20
-            }
-        }
-        traffic_generator.generate_samples = mock.Mock(return_value=samples)
-        traffic_generator.RUN_DURATION = 30
-        traffic_generator.rfc2544_helper.tolerance_low = 0.0001
-        traffic_generator.rfc2544_helper.tolerance_high = 0.0001
-        self.assertDictEqual(expected,
-                             r_f_c2544_profile.get_drop_percentage(traffic_generator))
+    @mock.patch.object(trex_stl_packet_builder_scapy, 'STLPktBuilder',
+                       return_value='packet')
+    def test__create_single_packet_qinq(self, mock_pktbuilder):
+        size = 128
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        rfc2544_profile.ether_packet = Pkt.Eth()
+        rfc2544_profile.ip_packet = Pkt.IP()
+        rfc2544_profile.udp_packet = Pkt.UDP()
+        rfc2544_profile.trex_vm = 'trex_vm'
+        rfc2544_profile.qinq = True
+        rfc2544_profile.qinq_packet = Pkt.Dot1Q(vlan=1) / Pkt.Dot1Q(vlan=2)
+        base_pkt = (rfc2544_profile.ether_packet /
+                    rfc2544_profile.qinq_packet / rfc2544_profile.ip_packet /
+                    rfc2544_profile.udp_packet)
+        pad = (size - len(base_pkt)) * 'x'
+        output = rfc2544_profile._create_single_packet(size=size)
+        mock_pktbuilder.assert_called_once_with(pkt=base_pkt / pad,
+                                                vm='trex_vm')
+        self.assertEqual(output, 'packet')
+
+    @mock.patch.object(trex_stl_streams, 'STLFlowLatencyStats')
+    @mock.patch.object(trex_stl_streams, 'STLTXCont')
+    @mock.patch.object(trex_stl_client, 'STLStream')
+    def test__create_streams(self, mock_stream, mock_txcont, mock_latency):
+        imix_data = {'64': 25, '512': 75}
+        rate = 35
+        port_pg_id = rfc2544.PortPgIDMap()
+        port_pg_id.add_port(10)
+        mock_stream.side_effect = ['stream1', 'stream2']
+        mock_txcont.side_effect = ['txcont1', 'txcont2']
+        mock_latency.side_effect = ['latency1', 'latency2']
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        with mock.patch.object(rfc2544_profile, '_create_single_packet'):
+            output = rfc2544_profile._create_streams(imix_data, rate,
+                                                     port_pg_id)
+        self.assertEqual(['stream1', 'stream2'], output)
+        mock_latency.assert_has_calls([
+            mock.call(pg_id=1), mock.call(pg_id=2)])
+        mock_txcont.assert_has_calls([
+            mock.call(percentage=float(25 * 35) / 100),
+            mock.call(percentage=float(75 * 35) / 100)], any_order=True)
+
+    def test_get_drop_percentage(self):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        samples = [
+            {'xe1': {'tx_throughput_fps': 100,
+                     'rx_throughput_fps': 101,
+                     'out_packets': 2000,
+                     'in_packets': 2010},
+             'xe2': {'tx_throughput_fps': 200,
+                     'rx_throughput_fps': 201,
+                     'out_packets': 4000,
+                     'in_packets': 4010}},
+            {'xe1': {'tx_throughput_fps': 106,
+                     'rx_throughput_fps': 108,
+                     'out_packets': 2031,
+                     'in_packets': 2040,
+                     'latency': 'Latency1'},
+             'xe2': {'tx_throughput_fps': 203,
+                     'rx_throughput_fps': 215,
+                     'out_packets': 4025,
+                     'in_packets': 4040,
+                     'latency': 'Latency2'}}
+        ]
+        output = rfc2544_profile.get_drop_percentage(samples, 0, 0, False)
+        expected = {'DropPercentage': 0.3963,
+                    'Latency': {'xe1': 'Latency1', 'xe2': 'Latency2'},
+                    'RxThroughput': 312.5,
+                    'TxThroughput': 304.5,
+                    'CurrentDropPercentage': 0.3963,
+                    'Rate': 100,
+                    'Throughput': 312.5}
+        self.assertEqual(expected, output)
 
-    def test_get_multiplier(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.max_rate = 100
-        r_f_c2544_profile.min_rate = 100
-        self.assertEqual("1.0", r_f_c2544_profile.get_multiplier())
 
-    def test_calculate_pps(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.rate = 100
-        r_f_c2544_profile.pps = 100
-        samples = {'Throughput': 4549093.33}
-        self.assertEqual((2274546.67, 1.0),
-                         r_f_c2544_profile.calculate_pps(samples))
+class PortPgIDMapTestCase(base.BaseUnitTestCase):
 
-    def test_create_single_stream(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile._create_single_packet = mock.MagicMock()
-        r_f_c2544_profile.pg_id = 1
-        self.assertIsNotNone(
-            r_f_c2544_profile.create_single_stream(64, 2274546.67))
+    def test_add_port(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        port_pg_id_map.add_port(10)
+        self.assertEqual(10, port_pg_id_map._last_port)
+        self.assertEqual([], port_pg_id_map._port_pg_id_map[10])
 
-    def test_create_single_stream_no_pg_id(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile._create_single_packet = mock.MagicMock()
-        r_f_c2544_profile.pg_id = 0
-        self.assertIsNotNone(
-            r_f_c2544_profile.create_single_stream(64, 2274546.67))
+    def test_get_pg_ids(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        port_pg_id_map.add_port(10)
+        port_pg_id_map.increase_pg_id()
+        port_pg_id_map.increase_pg_id()
+        port_pg_id_map.add_port(20)
+        port_pg_id_map.increase_pg_id()
+        self.assertEqual([1, 2], port_pg_id_map.get_pg_ids(10))
+        self.assertEqual([3], port_pg_id_map.get_pg_ids(20))
 
-    def test_execute_latency(self):
-        traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.networks = {
-            "private_0": ["xe0"],
-            "public_0": ["xe1"],
-        }
-        traffic_generator.client = \
-            mock.Mock(return_value=True)
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        r_f_c2544_profile.first_run = True
-        samples = {}
-        for ifname in range(1):
-            name = "xe{}".format(ifname)
-            samples[name] = {"rx_throughput_fps": 20,
-                             "tx_throughput_fps": 20,
-                             "rx_throughput_mbps": 10,
-                             "tx_throughput_mbps": 10,
-                             "in_packets": 1000,
-                             "out_packets": 0}
+    def test_increase_pg_id_no_port(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        self.assertIsNone(port_pg_id_map.increase_pg_id())
 
-        samples['Throughput'] = 4549093.33
-        r_f_c2544_profile.calculate_pps = mock.Mock(return_value=[2274546.67,
-                                                                  1.0])
+    def test_increase_pg_id_last_port(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        port_pg_id_map.add_port(10)
+        self.assertEqual(1, port_pg_id_map.increase_pg_id())
+        self.assertEqual([1], port_pg_id_map.get_pg_ids(10))
+        self.assertEqual(10, port_pg_id_map._last_port)
 
-        self.assertIsNone(r_f_c2544_profile.execute_latency(traffic_generator,
-                                                            samples))
+    def test_increase_pg_id(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        port_pg_id_map.add_port(10)
+        port_pg_id_map.increase_pg_id()
+        self.assertEqual(2, port_pg_id_map.increase_pg_id(port=20))
+        self.assertEqual([1], port_pg_id_map.get_pg_ids(10))
+        self.assertEqual([2], port_pg_id_map.get_pg_ids(20))
+        self.assertEqual(20, port_pg_id_map._last_port)
index 5fe1b73..628e854 100644 (file)
 
 import ipaddress
 
-import mock
 import six
 import unittest
 
-from yardstick.tests import STL_MOCKS
 from yardstick.common import exceptions as y_exc
-
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.traffic_profile.base import TrafficProfile
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import TrexProfile
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import SRC
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import DST
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import ETHERNET
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import IP
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import IPv6
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import UDP
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import SRC_PORT
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import DST_PORT
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import TYPE_OF_SERVICE
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import trex_traffic_profile
 
 
 class TestTrexProfile(unittest.TestCase):
@@ -59,7 +42,7 @@ class TestTrexProfile(unittest.TestCase):
         'name': 'rfc2544',
         'traffic_profile': {'traffic_type': 'RFC2544Profile',
                             'frame_rate': 100},
-        TrafficProfile.DOWNLINK: {
+        tp_base.TrafficProfile.DOWNLINK: {
             'ipv4': {'outer_l2': {'framesize': {'64B': '100',
                                                 '1518B': '0',
                                                 '128B': '0',
@@ -77,7 +60,7 @@ class TestTrexProfile(unittest.TestCase):
                      'outer_l4': {'srcport': '2001',
                                   'dsrport': '1234',
                                   'count': 1}}},
-        TrafficProfile.UPLINK: {
+        tp_base.TrafficProfile.UPLINK: {
             'ipv4':
                 {'outer_l2': {'framesize':
                                   {'64B': '100', '1518B': '0',
@@ -99,7 +82,7 @@ class TestTrexProfile(unittest.TestCase):
         'name': 'rfc2544',
         'traffic_profile': {'traffic_type': 'RFC2544Profile',
                             'frame_rate': 100},
-        TrafficProfile.DOWNLINK: {
+        tp_base.TrafficProfile.DOWNLINK: {
             'ipv6': {'outer_l2': {'framesize':
                                       {'64B': '100', '1518B': '0',
                                        '128B': '0', '1400B': '0',
@@ -118,7 +101,7 @@ class TestTrexProfile(unittest.TestCase):
                      'outer_l4': {'srcport': '2001',
                                   'dsrport': '1234',
                                   'count': 1}}},
-        TrafficProfile.UPLINK: {
+        tp_base.TrafficProfile.UPLINK: {
             'ipv6': {'outer_l2': {'framesize':
                                       {'64B': '100', '1518B': '0',
                                        '128B': '0', '1400B': '0',
@@ -140,17 +123,15 @@ class TestTrexProfile(unittest.TestCase):
         'schema': 'isb:traffic_profile:0.1'}
 
     def test___init__(self):
-        TrafficProfile.params = self.PROFILE
-        trex_profile = \
-            TrexProfile(TrafficProfile)
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         self.assertEqual(trex_profile.pps, 100)
 
     def test_qinq(self):
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         qinq = {"S-VLAN": {"id": 128, "priority": 0, "cfi": 0},
                 "C-VLAN": {"id": 512, "priority": 0, "cfi": 0}}
 
-        trex_profile = \
-            TrexProfile(TrafficProfile)
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         self.assertIsNone(trex_profile.set_qinq(qinq))
 
         qinq = {"S-VLAN": {"id": "128-130", "priority": 0, "cfi": 0},
@@ -158,64 +139,39 @@ class TestTrexProfile(unittest.TestCase):
         self.assertIsNone(trex_profile.set_qinq(qinq))
 
     def test__set_outer_l2_fields(self):
-        trex_profile = \
-            TrexProfile(TrafficProfile)
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         qinq = {"S-VLAN": {"id": 128, "priority": 0, "cfi": 0},
                 "C-VLAN": {"id": 512, "priority": 0, "cfi": 0}}
-        outer_l2 = self.PROFILE[TrafficProfile.UPLINK]['ipv4']['outer_l2']
+        outer_l2 = self.PROFILE[
+            tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l2']
         outer_l2['QinQ'] = qinq
         self.assertIsNone(trex_profile._set_outer_l2_fields(outer_l2))
 
     def test__set_outer_l3v4_fields(self):
-        trex_profile = \
-            TrexProfile(TrafficProfile)
-        outer_l3v4 = self.PROFILE[TrafficProfile.UPLINK]['ipv4']['outer_l3v4']
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        outer_l3v4 = self.PROFILE[
+            tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l3v4']
         outer_l3v4['proto'] = 'tcp'
         self.assertIsNone(trex_profile._set_outer_l3v4_fields(outer_l3v4))
 
     def test__set_outer_l3v6_fields(self):
-        trex_profile = \
-            TrexProfile(TrafficProfile)
-        outer_l3v6 = self.PROFILE_v6[TrafficProfile.UPLINK]['ipv6']['outer_l3v4']
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        outer_l3v6 = self.PROFILE_v6[
+            tp_base.TrafficProfile.UPLINK]['ipv6']['outer_l3v4']
         outer_l3v6['proto'] = 'tcp'
         outer_l3v6['tc'] = 1
         outer_l3v6['hlim'] = 10
         self.assertIsNone(trex_profile._set_outer_l3v6_fields(outer_l3v6))
 
     def test__set_outer_l4_fields(self):
-        trex_profile = \
-            TrexProfile(TrafficProfile)
-        outer_l4 = self.PROFILE[TrafficProfile.UPLINK]['ipv4']['outer_l4']
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        outer_l4 = self.PROFILE[
+            tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l4']
         self.assertIsNone(trex_profile._set_outer_l4_fields(outer_l4))
 
-    def test_get_streams(self):
-        trex_profile = \
-            TrexProfile(TrafficProfile)
-        trex_profile.params = self.PROFILE
-        profile_data = self.PROFILE[TrafficProfile.UPLINK]
-        self.assertIsNotNone(trex_profile.get_streams(profile_data))
-        trex_profile.pg_id = 1
-        self.assertIsNotNone(trex_profile.get_streams(profile_data))
-        trex_profile.params = self.PROFILE_v6
-        trex_profile.profile_data = self.PROFILE_v6[TrafficProfile.UPLINK]
-        self.assertIsNotNone(trex_profile.get_streams(profile_data))
-        trex_profile.pg_id = 1
-        self.assertIsNotNone(trex_profile.get_streams(profile_data))
-
-    def test_generate_packets(self):
-        trex_profile = \
-            TrexProfile(TrafficProfile)
-        trex_profile.fsize = 10
-        trex_profile.base_pkt = [10]
-        self.assertIsNone(trex_profile.generate_packets())
-
-    def test_generate_imix_data_error(self):
-        trex_profile = \
-            TrexProfile(TrafficProfile)
-        self.assertEqual({}, trex_profile.generate_imix_data(False))
-
     def test__count_ip_ipv4(self):
-        start, end, count = TrexProfile._count_ip('1.1.1.1', '1.2.3.4')
+        start, end, count = trex_traffic_profile.TrexProfile._count_ip(
+            '1.1.1.1', '1.2.3.4')
         self.assertEqual('1.1.1.1', str(start))
         self.assertEqual('1.2.3.4', str(end))
         diff = (int(ipaddress.IPv4Address(six.u('1.2.3.4'))) -
@@ -225,7 +181,8 @@ class TestTrexProfile(unittest.TestCase):
     def test__count_ip_ipv6(self):
         start_ip = '0064:ff9b:0:0:0:0:9810:6414'
         end_ip = '0064:ff9b:0:0:0:0:9810:6420'
-        start, end, count = TrexProfile._count_ip(start_ip, end_ip)
+        start, end, count = trex_traffic_profile.TrexProfile._count_ip(
+            start_ip, end_ip)
         self.assertEqual(0x98106414, start)
         self.assertEqual(0x98106420, end)
         self.assertEqual(0x98106420 - 0x98106414, count)
@@ -234,10 +191,10 @@ class TestTrexProfile(unittest.TestCase):
         start_ip = '0064:ff9b:0:0:0:0:9810:6420'
         end_ip = '0064:ff9b:0:0:0:0:9810:6414'
         with self.assertRaises(y_exc.IPv6RangeError):
-            TrexProfile._count_ip(start_ip, end_ip)
+            trex_traffic_profile.TrexProfile._count_ip(start_ip, end_ip)
 
     def test__dscp_range_action_partial_actual_count_zero(self):
-        traffic_profile = TrexProfile(TrafficProfile)
+        traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         dscp_partial = traffic_profile._dscp_range_action_partial()
 
         flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
@@ -245,7 +202,7 @@ class TestTrexProfile(unittest.TestCase):
         self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
 
     def test__dscp_range_action_partial_count_greater_than_actual(self):
-        traffic_profile = TrexProfile(TrafficProfile)
+        traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         dscp_partial = traffic_profile._dscp_range_action_partial()
 
         flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
@@ -253,7 +210,7 @@ class TestTrexProfile(unittest.TestCase):
         self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
 
     def test__udp_range_action_partial_actual_count_zero(self):
-        traffic_profile = TrexProfile(TrafficProfile)
+        traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         traffic_profile.udp['field1'] = 'value1'
         udp_partial = traffic_profile._udp_range_action_partial('field1')
 
@@ -262,48 +219,59 @@ class TestTrexProfile(unittest.TestCase):
         self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
 
     def test__udp_range_action_partial_count_greater_than_actual(self):
-        traffic_profile = TrexProfile(TrafficProfile)
+        traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         traffic_profile.udp['field1'] = 'value1'
-        udp_partial = traffic_profile._udp_range_action_partial('field1', 'not_used_count')
-
+        udp_partial = traffic_profile._udp_range_action_partial(
+            'field1', 'not_used_count')
         flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
         udp_partial('1', '10', '100')
         self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
 
     def test__general_single_action_partial(self):
-        trex_profile = TrexProfile(TrafficProfile)
-
-        trex_profile._general_single_action_partial(ETHERNET)(SRC)(
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        trex_profile._general_single_action_partial(
+            trex_traffic_profile.ETHERNET)(trex_traffic_profile.SRC)(
             self.EXAMPLE_ETHERNET_ADDR)
         self.assertEqual(self.EXAMPLE_ETHERNET_ADDR,
                          trex_profile.ether_packet.src)
 
-        trex_profile._general_single_action_partial(IP)(DST)(
-            self.EXAMPLE_IP_ADDR)
+        trex_profile._general_single_action_partial(trex_traffic_profile.IP)(
+            trex_traffic_profile.DST)(self.EXAMPLE_IP_ADDR)
         self.assertEqual(self.EXAMPLE_IP_ADDR, trex_profile.ip_packet.dst)
 
-        trex_profile._general_single_action_partial(IPv6)(DST)(
-            self.EXAMPLE_IPv6_ADDR)
+        trex_profile._general_single_action_partial(trex_traffic_profile.IPv6)(
+            trex_traffic_profile.DST)(self.EXAMPLE_IPv6_ADDR)
         self.assertEqual(self.EXAMPLE_IPv6_ADDR, trex_profile.ip6_packet.dst)
 
-        trex_profile._general_single_action_partial(UDP)(SRC_PORT)(5060)
+        trex_profile._general_single_action_partial(trex_traffic_profile.UDP)(
+            trex_traffic_profile.SRC_PORT)(5060)
         self.assertEqual(5060, trex_profile.udp_packet.sport)
 
-        trex_profile._general_single_action_partial(IP)(TYPE_OF_SERVICE)(0)
+        trex_profile._general_single_action_partial(trex_traffic_profile.IP)(
+            trex_traffic_profile.TYPE_OF_SERVICE)(0)
         self.assertEqual(0, trex_profile.ip_packet.tos)
 
     def test__set_proto_addr(self):
-        trex_profile = TrexProfile(TrafficProfile)
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
 
         ether_range = "00:00:00:00:00:01-00:00:00:00:00:02"
         ip_range = "1.1.1.2-1.1.1.10"
         ipv6_range = '0064:ff9b:0:0:0:0:9810:6414-0064:ff9b:0:0:0:0:9810:6420'
 
-        trex_profile._set_proto_addr(ETHERNET, SRC, ether_range)
-        trex_profile._set_proto_addr(ETHERNET, DST, ether_range)
-        trex_profile._set_proto_addr(IP, SRC, ip_range)
-        trex_profile._set_proto_addr(IP, DST, ip_range)
-        trex_profile._set_proto_addr(IPv6, SRC, ipv6_range)
-        trex_profile._set_proto_addr(IPv6, DST, ipv6_range)
-        trex_profile._set_proto_addr(UDP, SRC_PORT, "5060-5090")
-        trex_profile._set_proto_addr(UDP, DST_PORT, "5060")
+        trex_profile._set_proto_addr(trex_traffic_profile.ETHERNET,
+                                     trex_traffic_profile.SRC, ether_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.ETHERNET,
+                                     trex_traffic_profile.DST, ether_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.IP,
+                                     trex_traffic_profile.SRC, ip_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.IP,
+                                     trex_traffic_profile.DST, ip_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.IPv6,
+                                     trex_traffic_profile.SRC, ipv6_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.IPv6,
+                                     trex_traffic_profile.DST, ipv6_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.UDP,
+                                     trex_traffic_profile.SRC_PORT,
+                                     '5060-5090')
+        trex_profile._set_proto_addr(trex_traffic_profile.UDP,
+                                     trex_traffic_profile.DST_PORT, '5060')
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/acl_1rule.yaml b/yardstick/tests/unit/network_services/vnf_generic/vnf/acl_1rule.yaml
deleted file mode 100644 (file)
index b184a29..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (c) 2016-2017 Intel Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# 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.
-
-access-list1:
-  acl:
-    access-list-entries:
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 152.16.40.20/24
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 0.0.0.0/0
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1588
-    - ace:
-        ace-oper-data:
-          match-counter: 0
-        actions: drop,count
-        matches:
-          destination-ipv4-network: 0.0.0.0/0
-          destination-port-range:
-            lower-port: 0
-            upper-port: 65535
-          source-ipv4-network: 152.16.100.20/24
-          source-port-range:
-            lower-port: 0
-            upper-port: 65535
-        rule-name: rule1589
-    acl-name: sample-ipv4-acl
-    acl-type: ipv4-acl
index f75fa22..f04d2c6 100644 (file)
 import unittest
 import mock
 import os
+import re
+import copy
 
 from yardstick.tests import STL_MOCKS
 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
 from yardstick.common import utils
+from yardstick.common import exceptions
+from yardstick.benchmark.contexts import base as ctx_base
 
 
 STLClient = mock.MagicMock()
@@ -27,7 +31,8 @@ stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
 stl_patch.start()
 
 if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.acl_vnf import AclApproxVnf
+    from yardstick.network_services.vnf_generic.vnf import acl_vnf
+    from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
     from yardstick.network_services.nfvi.resource import ResourceProfile
     from yardstick.network_services.vnf_generic.vnf.acl_vnf import AclApproxSetupEnvSetupEnvHelper
 
@@ -142,7 +147,7 @@ class TestAclApproxVnf(unittest.TestCase):
                               'ip': '1.2.1.1',
                               'interfaces':
                               {'xe0': {'local_iface_name': 'ens513f0',
-                                       'vld_id': AclApproxVnf.DOWNLINK,
+                                       'vld_id': acl_vnf.AclApproxVnf.DOWNLINK,
                                        'netmask': '255.255.255.0',
                                        'local_ip': '152.16.40.20',
                                        'dst_mac': '00:00:00:00:00:01',
@@ -170,7 +175,7 @@ class TestAclApproxVnf(unittest.TestCase):
                               'ip': '1.2.1.1',
                               'interfaces':
                               {'xe0': {'local_iface_name': 'ens785f0',
-                                       'vld_id': AclApproxVnf.UPLINK,
+                                       'vld_id': acl_vnf.AclApproxVnf.UPLINK,
                                        'netmask': '255.255.255.0',
                                        'local_ip': '152.16.100.20',
                                        'dst_mac': '00:00:00:00:00:02',
@@ -195,7 +200,7 @@ class TestAclApproxVnf(unittest.TestCase):
                               'ip': '1.2.1.1',
                               'interfaces':
                               {'xe0': {'local_iface_name': 'ens786f0',
-                                       'vld_id': AclApproxVnf.UPLINK,
+                                       'vld_id': acl_vnf.AclApproxVnf.UPLINK,
                                        'netmask': '255.255.255.0',
                                        'local_ip': '152.16.100.19',
                                        'dst_mac': '00:00:00:00:00:04',
@@ -205,7 +210,7 @@ class TestAclApproxVnf(unittest.TestCase):
                                        'vpci': '0000:05:00.0',
                                        'dpdk_port_num': 0},
                                'xe1': {'local_iface_name': 'ens786f1',
-                                       'vld_id': AclApproxVnf.DOWNLINK,
+                                       'vld_id': acl_vnf.AclApproxVnf.DOWNLINK,
                                        'netmask': '255.255.255.0',
                                        'local_ip': '152.16.40.19',
                                        'dst_mac': '00:00:00:00:00:03',
@@ -241,22 +246,31 @@ class TestAclApproxVnf(unittest.TestCase):
 
     def test___init__(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        acl_approx_vnf = AclApproxVnf(name, vnfd)
+        acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
         self.assertIsNone(acl_approx_vnf._vnf_process)
 
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     @mock.patch(SSH_HELPER)
     def test_collect_kpi(self, ssh, *args):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        acl_approx_vnf = AclApproxVnf(name, vnfd)
+        acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
+        acl_approx_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {acl_approx_vnf.name: "mock"}
+        }
         acl_approx_vnf.q_in = mock.MagicMock()
         acl_approx_vnf.q_out = mock.MagicMock()
         acl_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
         acl_approx_vnf.resource = mock.Mock(autospec=ResourceProfile)
         acl_approx_vnf.vnf_execute = mock.Mock(return_value="")
-        result = {'packets_dropped': 0, 'packets_fwd': 0, 'packets_in': 0}
+        result = {
+            'physical_node': 'mock_node',
+            'packets_dropped': 0,
+            'packets_fwd': 0,
+            'packets_in': 0
+        }
         self.assertEqual(result, acl_approx_vnf.collect_kpi())
 
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
@@ -265,7 +279,7 @@ class TestAclApproxVnf(unittest.TestCase):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        acl_approx_vnf = AclApproxVnf(name, vnfd)
+        acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
         acl_approx_vnf.q_in = mock.MagicMock()
         acl_approx_vnf.q_out = mock.MagicMock()
         acl_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
@@ -277,7 +291,7 @@ class TestAclApproxVnf(unittest.TestCase):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        acl_approx_vnf = AclApproxVnf(name, vnfd)
+        acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
         acl_approx_vnf.q_in = mock.MagicMock()
         acl_approx_vnf.q_out = mock.MagicMock()
         acl_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
@@ -298,7 +312,7 @@ class TestAclApproxVnf(unittest.TestCase):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        acl_approx_vnf = AclApproxVnf(name, vnfd)
+        acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
         acl_approx_vnf._build_config = mock.MagicMock()
         acl_approx_vnf.queue_wrapper = mock.MagicMock()
         acl_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
@@ -311,7 +325,6 @@ class TestAclApproxVnf(unittest.TestCase):
         acl_approx_vnf._run()
         acl_approx_vnf.ssh_helper.run.assert_called_once()
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.acl_vnf.YangModel")
     @mock.patch.object(utils, 'find_relative_file')
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
     @mock.patch(SSH_HELPER)
@@ -319,7 +332,7 @@ class TestAclApproxVnf(unittest.TestCase):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        acl_approx_vnf = AclApproxVnf(name, vnfd)
+        acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
         acl_approx_vnf.deploy_helper = mock.MagicMock()
         acl_approx_vnf.resource_helper = mock.MagicMock()
         acl_approx_vnf._build_config = mock.MagicMock()
@@ -337,7 +350,7 @@ class TestAclApproxVnf(unittest.TestCase):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        acl_approx_vnf = AclApproxVnf(name, vnfd)
+        acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
         acl_approx_vnf._vnf_process = mock.MagicMock()
         acl_approx_vnf._vnf_process.terminate = mock.Mock()
         acl_approx_vnf.used_drivers = {"01:01.0": "i40e",
@@ -350,6 +363,145 @@ class TestAclApproxVnf(unittest.TestCase):
 
 class TestAclApproxSetupEnvSetupEnvHelper(unittest.TestCase):
 
+    ACL_CONFIG = {"access-list-entries": [{
+                     "actions": [
+                       "count",
+                       {"fwd": {
+                           "port": 0
+                         }
+                       }
+                     ],
+                     "matches": {
+                       "destination-ipv4-network": "152.16.0.0/24",
+                       "destination-port-range": {
+                         "lower-port": 0,
+                         "upper-port": 65535
+                       },
+                       "source-ipv4-network": "0.0.0.0/0",
+                       "source-port-range": {
+                         "lower-port": 0,
+                         "upper-port": 65535
+                       },
+                       "protocol-mask": 255,
+                       "protocol": 127,
+                       "priority": 1
+                     },
+                     "rule-name": "rule1588"
+                   }
+                 ]}
+
+    def test_get_default_flows(self):
+        """Check if default ACL SampleVNF CLI commands are
+        generated correctly"""
+        ssh_helper = mock.Mock()
+        vnfd_helper = VnfdHelper({'vdu': [
+            {'external-interface': [
+                {
+                    'virtual-interface': {
+                        'local_ip': '152.16.100.19',
+                        'netmask': '255.255.255.0',
+                        'dpdk_port_num': 0,
+                        'dst_ip': '152.16.100.20',
+                        'vld_id': 'uplink_0',
+                        'ifname': 'xe0',
+                    },
+                    'vnfd-connection-point-ref': 'xe0',
+                    'name': 'xe0'
+                },
+                {
+                    'virtual-interface': {
+                        'local_ip': '152.16.40.19',
+                        'netmask': '255.255.255.0',
+                        'dpdk_port_num': 1,
+                        'dst_ip': '152.16.40.20',
+                        'vld_id': 'downlink_0',
+                        'ifname': 'xe1',
+                    },
+                    'vnfd-connection-point-ref': 'xe1',
+                    'name': 'xe1'
+                }
+            ]}
+        ]})
+        setup_helper = AclApproxSetupEnvSetupEnvHelper(vnfd_helper, ssh_helper, None)
+        self.check_acl_commands(setup_helper.get_flows_config(), [
+            # format: (<cli pattern>, <number of expected matches>)
+            ("^p action add [0-9]+ accept$", 2),
+            ("^p action add [0-9]+ count$", 2),
+            ("^p action add [0-9]+ fwd 1$", 1),
+            ("^p action add [0-9]+ fwd 0$", 1),
+            ("^p acl add 1 152.16.100.0 24 152.16.40.0 24 0 65535 0 65535 0 0 [0-9]+$", 1),
+            ("^p acl add 1 152.16.40.0 24 152.16.100.0 24 0 65535 0 65535 0 0 [0-9]+$", 1),
+            ("^p acl applyruleset$", 1)
+        ])
+
+    @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
+    def test_get_flows_config(self, get_default_flows):
+        """Check if provided ACL config can be converted to
+        ACL SampleVNF CLI commands correctly"""
+        ssh_helper = mock.Mock()
+        setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
+        get_default_flows.return_value = ({}, [])
+        self.check_acl_commands(setup_helper.get_flows_config(self.ACL_CONFIG), [
+            # format: (<cli pattern>, <number of expected matches>)
+            ("^p action add [0-9]+ count$", 1),
+            ("^p action add [0-9]+ fwd 0$", 1),
+            ("^p acl add 1 0.0.0.0 0 152.16.0.0 24 0 65535 0 65535 127 0 [0-9]+$", 1),
+            ("^p acl applyruleset$", 1)
+        ])
+
+    @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
+    def test_get_flows_config_invalid_action(self, get_default_flows):
+        """Check if incorrect ACL config fails to convert
+        to ACL SampleVNF CLI commands"""
+        ssh_helper = mock.Mock()
+        setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
+        get_default_flows.return_value = ({}, [])
+        # duplicate config and add invald action
+        acl_config = copy.deepcopy(self.ACL_CONFIG)
+        acl_config['access-list-entries'][0]["actions"].append({"xnat": {}})
+        self.assertRaises(exceptions.AclUknownActionTemplate,
+            setup_helper.get_flows_config, acl_config)
+
+    @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
+    def test_get_flows_config_invalid_action_param(self, get_default_flows):
+        """Check if ACL config with invalid action parameter fails to convert
+        to ACL SampleVNF CLI commands"""
+        ssh_helper = mock.Mock()
+        setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
+        get_default_flows.return_value = ({}, [])
+        # duplicate config and add action with invalid parameter
+        acl_config = copy.deepcopy(self.ACL_CONFIG)
+        acl_config['access-list-entries'][0]["actions"].append(
+            {"nat": {"xport": 0}})
+        self.assertRaises(exceptions.AclMissingActionArguments,
+            setup_helper.get_flows_config, acl_config)
+
+    def check_acl_commands(self, config, expected_cli_patterns):
+        """Check if expected ACL CLI commands (given as a list of patterns,
+        `expected_cli_patterns` parameter) present in SampleVNF ACL
+        configuration (given as a multiline string, `config` parameter)"""
+        # Example of expected config:
+        # ---------------------------
+        # p action add 1 accept
+        # p action add 1 fwd 1
+        # p action add 2 accept
+        # p action add 2 count
+        # p action add 2 fwd 0
+        # p acl add 1 152.16.100.0 24 152.16.40.0 24 0 65535 0 65535 0 0 1
+        # p acl add 1 152.16.40.0 24 152.16.100.0 24 0 65535 0 65535 0 0 2
+        # p acl applyruleset
+        # ---------------------------
+        # NOTE: The config above consists of actions ids, which are actually
+        # unknown (generated at runtime), thus it's incorrect just to compare
+        # the example ACL config above with the configuration returned by
+        # get_flows_config() function. It's more correct to use CLI patterns
+        # (RE) to find the required SampleVNF CLI commands in the multiline
+        # string (SampleVNF ACL configuration).
+        for pattern, num_of_match in expected_cli_patterns:
+            # format: (<cli pattern>, <number of expected matches>)
+            result = re.findall(pattern, config, re.MULTILINE)
+            self.assertEqual(len(result), num_of_match)
+
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.open')
     @mock.patch.object(utils, 'find_relative_file')
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig')
@@ -359,14 +511,17 @@ class TestAclApproxSetupEnvSetupEnvHelper(unittest.TestCase):
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+        scenario_helper.options = {}
         scenario_helper.all_options = {}
 
         acl_approx_setup_helper = AclApproxSetupEnvSetupEnvHelper(vnfd_helper,
                                                                   ssh_helper,
                                                                   scenario_helper)
 
+        acl_approx_setup_helper.get_flows_config = mock.Mock()
         acl_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
         acl_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
         acl_approx_setup_helper.vnfd_helper.port_nums = mock.Mock(return_value=[0, 1])
         expected = 'sudo tool_path -p 0x3 -f /tmp/acl_config -s /tmp/acl_script  --hwlb 3'
         self.assertEqual(acl_approx_setup_helper.build_config(), expected)
+        acl_approx_setup_helper.get_flows_config.assert_called_once()
index ebedcb4..43e5ac8 100644 (file)
 
 import multiprocessing
 import os
+import uuid
 
 import mock
+from oslo_config import cfg
+import oslo_messaging
 import unittest
 
+from yardstick.common import messaging
+from yardstick.common.messaging import payloads
 from yardstick.network_services.vnf_generic.vnf import base
 from yardstick.ssh import SSH
 
@@ -140,6 +145,24 @@ VNFD = {
 }
 
 
+class _DummyGenericTrafficGen(base.GenericTrafficGen):  # pragma: no cover
+
+    def run_traffic(self, *args):
+        pass
+
+    def terminate(self):
+        pass
+
+    def collect_kpi(self):
+        pass
+
+    def instantiate(self, *args):
+        pass
+
+    def scale(self, flavor=''):
+        pass
+
+
 class FileAbsPath(object):
     def __init__(self, module_file):
         super(FileAbsPath, self).__init__()
@@ -221,7 +244,7 @@ class TestGenericVNF(unittest.TestCase):
         self.assertEqual(msg, str(exc.exception))
 
 
-class TestGenericTrafficGen(unittest.TestCase):
+class GenericTrafficGenTestCase(unittest.TestCase):
 
     def test_definition(self):
         """Make sure that the abstract class cannot be instantiated"""
@@ -234,3 +257,81 @@ class TestGenericTrafficGen(unittest.TestCase):
                "abstract methods collect_kpi, instantiate, run_traffic, "
                "scale, terminate")
         self.assertEqual(msg, str(exc.exception))
+
+    def test_get_mq_producer_id(self):
+        vnfd = {'benchmark': {'kpi': mock.ANY},
+                'vdu': [{'external-interface': 'ext_int'}]
+                }
+        tg = _DummyGenericTrafficGen('name', vnfd)
+        tg._mq_producer = mock.Mock()
+        tg._mq_producer.get_id.return_value = 'fake_id'
+        self.assertEqual('fake_id', tg.get_mq_producer_id())
+
+
+class TrafficGeneratorProducerTestCase(unittest.TestCase):
+
+    @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
+    @mock.patch.object(oslo_messaging, 'RPCClient')
+    @mock.patch.object(oslo_messaging, 'get_rpc_transport',
+                       return_value='rpc_transport')
+    @mock.patch.object(cfg, 'CONF')
+    def test__init(self, mock_config, mock_transport, mock_rpcclient,
+                   mock_target):
+        _id = uuid.uuid1().int
+        tg_producer = base.TrafficGeneratorProducer(_id)
+        mock_transport.assert_called_once_with(
+            mock_config, url='rabbit://yardstick:yardstick@localhost:5672/')
+        mock_target.assert_called_once_with(topic=messaging.TOPIC_TG,
+                                            fanout=True,
+                                            server=messaging.SERVER)
+        mock_rpcclient.assert_called_once_with('rpc_transport', 'rpc_target')
+        self.assertEqual(_id, tg_producer._id)
+        self.assertEqual(messaging.TOPIC_TG, tg_producer._topic)
+
+    @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
+    @mock.patch.object(oslo_messaging, 'RPCClient')
+    @mock.patch.object(oslo_messaging, 'get_rpc_transport',
+                       return_value='rpc_transport')
+    @mock.patch.object(payloads, 'TrafficGeneratorPayload',
+                       return_value='tg_pload')
+    def test_tg_method_started(self, mock_tg_payload, *args):
+        tg_producer = base.TrafficGeneratorProducer(uuid.uuid1().int)
+        with mock.patch.object(tg_producer, 'send_message') as mock_message:
+            tg_producer.tg_method_started(version=10)
+
+        mock_message.assert_called_once_with(messaging.TG_METHOD_STARTED,
+                                             'tg_pload')
+        mock_tg_payload.assert_called_once_with(version=10, iteration=0,
+                                                kpi={})
+
+    @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
+    @mock.patch.object(oslo_messaging, 'RPCClient')
+    @mock.patch.object(oslo_messaging, 'get_rpc_transport',
+                       return_value='rpc_transport')
+    @mock.patch.object(payloads, 'TrafficGeneratorPayload',
+                       return_value='tg_pload')
+    def test_tg_method_finished(self, mock_tg_payload, *args):
+        tg_producer = base.TrafficGeneratorProducer(uuid.uuid1().int)
+        with mock.patch.object(tg_producer, 'send_message') as mock_message:
+            tg_producer.tg_method_finished(version=20)
+
+        mock_message.assert_called_once_with(messaging.TG_METHOD_FINISHED,
+                                             'tg_pload')
+        mock_tg_payload.assert_called_once_with(version=20, iteration=0,
+                                                kpi={})
+
+    @mock.patch.object(oslo_messaging, 'Target', return_value='rpc_target')
+    @mock.patch.object(oslo_messaging, 'RPCClient')
+    @mock.patch.object(oslo_messaging, 'get_rpc_transport',
+                       return_value='rpc_transport')
+    @mock.patch.object(payloads, 'TrafficGeneratorPayload',
+                       return_value='tg_pload')
+    def test_tg_method_iteration(self, mock_tg_payload, *args):
+        tg_producer = base.TrafficGeneratorProducer(uuid.uuid1().int)
+        with mock.patch.object(tg_producer, 'send_message') as mock_message:
+            tg_producer.tg_method_iteration(100, version=30, kpi={'k': 'v'})
+
+        mock_message.assert_called_once_with(messaging.TG_METHOD_ITERATION,
+                                             'tg_pload')
+        mock_tg_payload.assert_called_once_with(version=30, iteration=100,
+                                                kpi={'k': 'v'})
index bd8f53e..635ca41 100644 (file)
 # 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.
-#
 
 from copy import deepcopy
-import os
+import time
 
 import mock
 import unittest
 
-
+from yardstick.benchmark.contexts import base as ctx_base
 from yardstick.common import utils
-
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
-
-
-
-from yardstick.network_services.vnf_generic.vnf.cgnapt_vnf import CgnaptApproxVnf, \
-    CgnaptApproxSetupEnvHelper
+from yardstick.common import process
 from yardstick.network_services.vnf_generic.vnf import cgnapt_vnf
-from yardstick.network_services.nfvi.resource import ResourceProfile
-
-TEST_FILE_YAML = 'nsb_test_case.yaml'
-SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.nfvi import resource
 
 
+TEST_FILE_YAML = 'nsb_test_case.yaml'
 name = 'vnf__0'
 
 
@@ -42,8 +34,9 @@ class TestCgnaptApproxSetupEnvHelper(unittest.TestCase):
 
     def test__generate_ip_from_pool(self):
 
-        ip = CgnaptApproxSetupEnvHelper._generate_ip_from_pool("1.2.3.4")
-        self.assertEqual(next(ip), '1.2.3.4')
+        _ip = '1.2.3.4'
+        ip = cgnapt_vnf.CgnaptApproxSetupEnvHelper._generate_ip_from_pool(_ip)
+        self.assertEqual(next(ip), _ip)
         self.assertEqual(next(ip), '1.2.4.4')
         self.assertEqual(next(ip), '1.2.5.4')
 
@@ -62,19 +55,22 @@ link 1 up
 """
         header = "This is a header"
 
-        out = CgnaptApproxSetupEnvHelper._update_cgnat_script_file(header, sample.splitlines())
+        out = cgnapt_vnf.CgnaptApproxSetupEnvHelper._update_cgnat_script_file(
+            header, sample.splitlines())
         self.assertNotIn("This is a header", out)
 
     def test__get_cgnapt_config(self):
         vnfd_helper = mock.MagicMock()
         vnfd_helper.port_pairs.uplink_ports = [{"name": 'a'}, {"name": "b"}, {"name": "c"}]
 
-        helper = CgnaptApproxSetupEnvHelper(vnfd_helper, mock.Mock(), mock.Mock())
+        helper = cgnapt_vnf.CgnaptApproxSetupEnvHelper(
+            vnfd_helper, mock.Mock(), mock.Mock())
         result = helper._get_cgnapt_config()
         self.assertIsNotNone(result)
 
     def test_scale(self):
-        helper = CgnaptApproxSetupEnvHelper(mock.Mock(), mock.Mock(), mock.Mock())
+        helper = cgnapt_vnf.CgnaptApproxSetupEnvHelper(
+            mock.Mock(), mock.Mock(), mock.Mock())
         with self.assertRaises(NotImplementedError):
             helper.scale()
 
@@ -87,11 +83,11 @@ link 1 up
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+        scenario_helper.options = {}
         scenario_helper.all_options = {}
 
-        cgnat_approx_setup_helper = CgnaptApproxSetupEnvHelper(vnfd_helper,
-                                                               ssh_helper,
-                                                               scenario_helper)
+        cgnat_approx_setup_helper = cgnapt_vnf.CgnaptApproxSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
 
         cgnat_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
         cgnat_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
@@ -100,7 +96,7 @@ link 1 up
         self.assertEqual(cgnat_approx_setup_helper.build_config(), expected)
 
 
-@mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process")
+@mock.patch.object(sample_vnf, 'Process')
 class TestCgnaptApproxVnf(unittest.TestCase):
     VNFD = {'vnfd:vnfd-catalog':
             {'vnfd':
@@ -220,7 +216,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
                               'ip': '1.2.1.1',
                               'interfaces':
                               {'xe0': {'local_iface_name': 'ens513f0',
-                                       'vld_id': CgnaptApproxVnf.DOWNLINK,
+                                       'vld_id': cgnapt_vnf.CgnaptApproxVnf.DOWNLINK,
                                        'netmask': '255.255.255.0',
                                        'local_ip': '152.16.40.20',
                                        'dst_mac': '00:00:00:00:00:01',
@@ -248,7 +244,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
                               'ip': '1.2.1.1',
                               'interfaces':
                               {'xe0': {'local_iface_name': 'ens785f0',
-                                       'vld_id': CgnaptApproxVnf.UPLINK,
+                                       'vld_id': cgnapt_vnf.CgnaptApproxVnf.UPLINK,
                                        'netmask': '255.255.255.0',
                                        'local_ip': '152.16.100.20',
                                        'dst_mac': '00:00:00:00:00:02',
@@ -273,7 +269,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
                               'ip': '1.2.1.1',
                               'interfaces':
                               {'xe0': {'local_iface_name': 'ens786f0',
-                                       'vld_id': CgnaptApproxVnf.UPLINK,
+                                       'vld_id': cgnapt_vnf.CgnaptApproxVnf.UPLINK,
                                        'netmask': '255.255.255.0',
                                        'local_ip': '152.16.100.19',
                                        'dst_mac': '00:00:00:00:00:04',
@@ -283,7 +279,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
                                        'vpci': '0000:05:00.0',
                                        'dpdk_port_num': 0},
                                'xe1': {'local_iface_name': 'ens786f1',
-                                       'vld_id': CgnaptApproxVnf.DOWNLINK,
+                                       'vld_id': cgnapt_vnf.CgnaptApproxVnf.DOWNLINK,
                                        'netmask': '255.255.255.0',
                                        'local_ip': '152.16.40.19',
                                        'dst_mac': '00:00:00:00:00:03',
@@ -322,81 +318,68 @@ class TestCgnaptApproxVnf(unittest.TestCase):
 
     def test___init__(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
+        cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
         self.assertIsNone(cgnapt_approx_vnf._vnf_process)
 
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
-    @mock.patch(SSH_HELPER)
-    def test_collect_kpi(self, ssh, *args):
-        mock_ssh(ssh)
-
+    @mock.patch.object(process, 'check_if_process_failed')
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+    def test_collect_kpi(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
+        cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+        cgnapt_approx_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {cgnapt_approx_vnf.name: "mock"}
+        }
         cgnapt_approx_vnf._vnf_process = mock.MagicMock(
             **{"is_alive.return_value": True, "exitcode": None})
         cgnapt_approx_vnf.q_in = mock.MagicMock()
         cgnapt_approx_vnf.q_out = mock.MagicMock()
         cgnapt_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
-        cgnapt_approx_vnf.resource = mock.Mock(autospec=ResourceProfile)
-        result = {'packets_dropped': 0, 'packets_fwd': 0, 'packets_in': 0}
-        self.assertEqual(result, cgnapt_approx_vnf.collect_kpi())
-
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
-    @mock.patch(SSH_HELPER)
-    def test_vnf_execute_command(self, ssh, *args):
-        mock_ssh(ssh)
-
+        cgnapt_approx_vnf.resource = mock.Mock(
+            autospec=resource.ResourceProfile)
+        result = {
+            'physical_node': 'mock_node',
+            'packets_dropped': 0,
+            'packets_fwd': 0,
+            'packets_in': 0
+        }
+        with mock.patch.object(cgnapt_approx_vnf, 'get_stats',
+                               return_value=''):
+            self.assertEqual(result, cgnapt_approx_vnf.collect_kpi())
+
+    @mock.patch.object(time, 'sleep')
+    def test_vnf_execute_command(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
-        cgnapt_approx_vnf.q_in = mock.MagicMock()
-        cgnapt_approx_vnf.q_out = mock.MagicMock()
+        cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+        cgnapt_approx_vnf.q_in = mock.Mock()
+        cgnapt_approx_vnf.q_out = mock.Mock()
         cgnapt_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
-        cmd = "quit"
-        self.assertEqual("", cgnapt_approx_vnf.vnf_execute(cmd))
-
-    @mock.patch(SSH_HELPER)
-    def test_get_stats(self, ssh, *args):
-        mock_ssh(ssh)
+        self.assertEqual("", cgnapt_approx_vnf.vnf_execute('quit'))
 
+    def test_get_stats(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
-        cgnapt_approx_vnf.q_in = mock.MagicMock()
-        cgnapt_approx_vnf.q_out = mock.MagicMock()
-        cgnapt_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
-        result = \
-            "CG-NAPT(.*\n)*Received 100, Missed 0, Dropped 0,Translated 100,ingress"
-        cgnapt_approx_vnf.vnf_execute = mock.Mock(return_value=result)
-        self.assertListEqual(list(result), list(cgnapt_approx_vnf.get_stats()))
-
-    def _get_file_abspath(self, filename):
-        curr_path = os.path.dirname(os.path.abspath(__file__))
-        file_path = os.path.join(curr_path, filename)
-        return file_path
-
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.cgnapt_vnf.hex")
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.cgnapt_vnf.eval")
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.cgnapt_vnf.open')
-    @mock.patch(SSH_HELPER)
-    def test_run_vcgnapt(self, ssh, *args):
-        mock_ssh(ssh)
+        cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+        with mock.patch.object(cgnapt_approx_vnf, 'vnf_execute') as mock_exec:
+            mock_exec.return_value = 'output'
+            self.assertEqual('output', cgnapt_approx_vnf.get_stats())
+
+        mock_exec.assert_called_once_with('p cgnapt stats')
 
+    def test_run_vcgnapt(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
-        cgnapt_approx_vnf._build_config = mock.MagicMock()
-        cgnapt_approx_vnf.queue_wrapper = mock.MagicMock()
-        cgnapt_approx_vnf.ssh_helper = mock.MagicMock()
-        cgnapt_approx_vnf.ssh_helper.run = mock.MagicMock()
-        cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
-        cgnapt_approx_vnf._run()
-        cgnapt_approx_vnf.ssh_helper.run.assert_called_once()
+        cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+        cgnapt_approx_vnf.ssh_helper = mock.Mock()
+        cgnapt_approx_vnf.setup_helper = mock.Mock()
+        with mock.patch.object(cgnapt_approx_vnf, '_build_config'), \
+                mock.patch.object(cgnapt_approx_vnf, '_build_run_kwargs'):
+            cgnapt_approx_vnf._run()
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
-    @mock.patch(SSH_HELPER)
-    def test_instantiate(self, ssh, *args):
-        mock_ssh(ssh)
+        cgnapt_approx_vnf.ssh_helper.run.assert_called_once()
+        cgnapt_approx_vnf.setup_helper.kill_vnf.assert_called_once()
 
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server')
+    def test_instantiate(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
+        cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
         cgnapt_approx_vnf.deploy_helper = mock.MagicMock()
         cgnapt_approx_vnf.resource_helper = mock.MagicMock()
         cgnapt_approx_vnf._build_config = mock.MagicMock()
@@ -405,51 +388,25 @@ class TestCgnaptApproxVnf(unittest.TestCase):
         cgnapt_approx_vnf.q_out.put("pipeline>")
         cgnapt_vnf.WAIT_TIME = 3
         self.scenario_cfg.update({"nodes": {"vnf__0": ""}})
-        self.assertIsNone(cgnapt_approx_vnf.instantiate(self.scenario_cfg,
-                                                        self.context_cfg))
-
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
-    @mock.patch(SSH_HELPER)
-    def test_terminate(self, ssh, *args):
-        mock_ssh(ssh)
-
-        vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
-        cgnapt_approx_vnf._vnf_process = mock.MagicMock()
-        cgnapt_approx_vnf._vnf_process.terminate = mock.Mock()
-        cgnapt_approx_vnf.used_drivers = {"01:01.0": "i40e",
-                                          "01:01.1": "i40e"}
-        cgnapt_approx_vnf.vnf_execute = mock.MagicMock()
-        cgnapt_approx_vnf.dpdk_nic_bind = "dpdk_nic_bind.py"
-        cgnapt_approx_vnf._resource_collect_stop = mock.Mock()
-        self.assertIsNone(cgnapt_approx_vnf.terminate())
-
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
-    @mock.patch(SSH_HELPER)
-    def test__vnf_up_post(self, ssh, *args):
-        mock_ssh(ssh)
+        with mock.patch.object(cgnapt_approx_vnf, '_start_vnf'):
+            self.assertIsNone(cgnapt_approx_vnf.instantiate(
+                self.scenario_cfg, self.context_cfg))
 
+    @mock.patch.object(time, 'sleep')
+    def test__vnf_up_post(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         self.scenario_cfg['options'][name]['napt'] = 'static'
-
-        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
-        cgnapt_approx_vnf._vnf_process = mock.MagicMock()
-        cgnapt_approx_vnf._vnf_process.terminate = mock.Mock()
-        cgnapt_approx_vnf.vnf_execute = mock.MagicMock()
+        cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+        cgnapt_approx_vnf.vnf_execute = mock.Mock()
         cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
-        cgnapt_approx_vnf._resource_collect_stop = mock.Mock()
-        cgnapt_approx_vnf._vnf_up_post()
-
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
-    @mock.patch(SSH_HELPER)
-    def test__vnf_up_post_short(self, ssh, *args):
-        mock_ssh(ssh)
+        with mock.patch.object(cgnapt_approx_vnf, 'setup_helper') as \
+                mock_setup_helper:
+            mock_setup_helper._generate_ip_from_pool.return_value = ['ip1']
+            mock_setup_helper._get_cgnapt_config.return_value = ['gw_ip1']
+            cgnapt_approx_vnf._vnf_up_post()
 
+    def test__vnf_up_post_short(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
-        cgnapt_approx_vnf._vnf_process = mock.MagicMock()
-        cgnapt_approx_vnf._vnf_process.terminate = mock.Mock()
-        cgnapt_approx_vnf.vnf_execute = mock.MagicMock()
+        cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
         cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
-        cgnapt_approx_vnf._resource_collect_stop = mock.Mock()
         cgnapt_approx_vnf._vnf_up_post()
index c74a6cf..3b09564 100644 (file)
@@ -1,4 +1,3 @@
-
 # Copyright (c) 2016-2017 Intel Corporation
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,7 +11,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
 
 from itertools import repeat, chain
 import os
@@ -22,39 +20,21 @@ import time
 import mock
 import unittest
 
-from yardstick.tests import STL_MOCKS
 from yardstick.common import utils
-from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
 from yardstick.network_services import constants
+from yardstick.network_services.vnf_generic.vnf import base as vnf_base
+from yardstick.network_services.vnf_generic.vnf import prox_helpers
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
 
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxSocketHelper
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import PacketDump
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import CoreSocketTuple
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxTestDataTuple
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxDpdkVnfSetupEnvHelper
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import TotStatsTuple
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxDataHelper
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxResourceHelper
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxProfileHelper
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxMplsProfileHelper
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxBngProfileHelper
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxVpeProfileHelper
-    from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxlwAFTRProfileHelper
 
 class TestCoreTuple(unittest.TestCase):
     def test___init__(self):
-        core_tuple = CoreSocketTuple('core 5s6')
+        core_tuple = prox_helpers.CoreSocketTuple('core 5s6')
         self.assertEqual(core_tuple.core_id, 5)
         self.assertEqual(core_tuple.socket_id, 6)
         self.assertFalse(core_tuple.is_hyperthread())
 
-        core_tuple = CoreSocketTuple('core 5s6h')
+        core_tuple = prox_helpers.CoreSocketTuple('core 5s6h')
         self.assertEqual(core_tuple.core_id, 5)
         self.assertEqual(core_tuple.socket_id, 6)
         self.assertTrue(core_tuple.is_hyperthread())
@@ -82,7 +62,7 @@ class TestCoreTuple(unittest.TestCase):
 
         for bad_input in bad_inputs:
             with self.assertRaises(ValueError):
-                CoreSocketTuple(bad_input)
+                prox_helpers.CoreSocketTuple(bad_input)
 
     def test_find_in_topology(self):
         topology_in = {
@@ -94,20 +74,20 @@ class TestCoreTuple(unittest.TestCase):
             },
         }
 
-        core_tuple = CoreSocketTuple('core 5s6')
+        core_tuple = prox_helpers.CoreSocketTuple('core 5s6')
 
         expected = 'a'
         result = core_tuple.find_in_topology(topology_in)
         self.assertEqual(result, expected)
 
-        core_tuple = CoreSocketTuple('core 5s6h')
+        core_tuple = prox_helpers.CoreSocketTuple('core 5s6h')
 
         expected = 'c'
         result = core_tuple.find_in_topology(topology_in)
         self.assertEqual(result, expected)
 
     def test_find_in_topology_negative(self):
-        core_tuple = CoreSocketTuple('core 6s5')
+        core_tuple = prox_helpers.CoreSocketTuple('core 6s5')
         with self.assertRaises(ValueError):
             # no socket key
             core_tuple.find_in_topology({})
@@ -120,7 +100,7 @@ class TestCoreTuple(unittest.TestCase):
             # no first value (as needed by non-hyperthread core)
             core_tuple.find_in_topology({5: {6: {'key1': []}}})
 
-        core_tuple = CoreSocketTuple('core 6s5h')
+        core_tuple = prox_helpers.CoreSocketTuple('core 6s5h')
         with self.assertRaises(ValueError):
             # no second value (as needed by hyperthread core)
             core_tuple.find_in_topology({5: {6: {'key1': ['e']}}})
@@ -130,20 +110,21 @@ class TestTotStatsTuple(unittest.TestCase):
     def test___new___negative(self):
         with self.assertRaises(TypeError):
             # no values
-            TotStatsTuple()
+            prox_helpers.TotStatsTuple()
 
         with self.assertRaises(TypeError):
             # one, non-integer value
-            TotStatsTuple('a')
+            prox_helpers.TotStatsTuple('a')
 
         with self.assertRaises(TypeError):
             # too many values
-            TotStatsTuple(3, 4, 5, 6, 7)
+            prox_helpers.TotStatsTuple(3, 4, 5, 6, 7)
 
 
 class TestProxTestDataTuple(unittest.TestCase):
     def test___init__(self):
-        prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, 6, 7, 8, 9)
+        prox_test_data = prox_helpers.ProxTestDataTuple(
+            1, 2, 3, 4, 5, 6, 7, 8, 9)
         self.assertEqual(prox_test_data.tolerated, 1)
         self.assertEqual(prox_test_data.tsc_hz, 2)
         self.assertEqual(prox_test_data.delta_rx, 3)
@@ -155,22 +136,26 @@ class TestProxTestDataTuple(unittest.TestCase):
         self.assertEqual(prox_test_data.requested_pps, 9)
 
     def test_properties(self):
-        prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, 6, 7, 8, 9)
+        prox_test_data = prox_helpers.ProxTestDataTuple(
+            1, 2, 3, 4, 5, 6, 7, 8, 9)
         self.assertEqual(prox_test_data.pkt_loss, 12.5)
         self.assertEqual(prox_test_data.tx_mpps, 1.6 / 1e6)
         self.assertEqual(prox_test_data.can_be_lost, 0)
         self.assertEqual(prox_test_data.drop_total, 1)
         self.assertFalse(prox_test_data.success)
 
-        prox_test_data = ProxTestDataTuple(10, 2, 3, 4, 5, 6, 997, 998, 9)
+        prox_test_data = prox_helpers.ProxTestDataTuple(
+            10, 2, 3, 4, 5, 6, 997, 998, 9)
         self.assertTrue(prox_test_data.success)
 
     def test_pkt_loss_zero_division(self):
-        prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, 6, 7, 0, 9)
+        prox_test_data = prox_helpers.ProxTestDataTuple(
+            1, 2, 3, 4, 5, 6, 7, 0, 9)
         self.assertEqual(prox_test_data.pkt_loss, 100.0)
 
     def test_get_samples(self):
-        prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, [6.1, 6.9, 6.4], 7, 8, 9)
+        prox_test_data = prox_helpers.ProxTestDataTuple(
+            1, 2, 3, 4, 5, [6.1, 6.9, 6.4], 7, 8, 9)
 
         expected = {
             "Throughput": 1.2 / 1e6,
@@ -206,38 +191,41 @@ class TestProxTestDataTuple(unittest.TestCase):
     @mock.patch('yardstick.LOG_RESULT', create=True)
     def test_log_data(self, mock_logger):
         my_mock_logger = mock.MagicMock()
-        prox_test_data = ProxTestDataTuple(1, 2, 3, 4, 5, [6.1, 6.9, 6.4], 7, 8, 9)
+        prox_test_data = prox_helpers.ProxTestDataTuple(
+            1, 2, 3, 4, 5, [6.1, 6.9, 6.4], 7, 8, 9)
         prox_test_data.log_data()
-        self.assertEqual(my_mock_logger.debug.call_count, 0)
-        self.assertEqual(mock_logger.debug.call_count, 0)
+
+        my_mock_logger.debug.assert_not_called()
+        mock_logger.debug.assert_not_called()
 
         mock_logger.debug.reset_mock()
         prox_test_data.log_data(my_mock_logger)
-        self.assertEqual(my_mock_logger.debug.call_count, 0)
-        self.assertEqual(mock_logger.debug.call_count, 0)
+        my_mock_logger.assert_not_called()
+        mock_logger.debug.assert_not_called()
 
 
 class TestPacketDump(unittest.TestCase):
     PAYLOAD = "payload"
 
     def test__init__(self):
-        PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
+        prox_helpers.PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
 
     def test___str__(self):
         expected = '<PacketDump port: port_id payload: {}>'.format(self.PAYLOAD)
-        dump1 = PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
+        dump1 = prox_helpers.PacketDump(
+            "port_id", len(self.PAYLOAD), self.PAYLOAD)
         self.assertEqual(str(dump1), expected)
 
     def test_port_id(self):
-        p = PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
+        p = prox_helpers.PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
         self.assertEqual(p.port_id, "port_id")
 
     def test_data_len(self):
-        p = PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
+        p = prox_helpers.PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
         self.assertEqual(p.data_len, len(self.PAYLOAD))
 
     def test_payload(self):
-        p = PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
+        p = prox_helpers.PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
         self.assertEqual(p.payload(), self.PAYLOAD)
 
         self.assertEqual(p.payload(3), self.PAYLOAD[3:])
@@ -293,35 +281,40 @@ no data length value
 class TestProxSocketHelper(unittest.TestCase):
 
     def setUp(self):
-        self.mock_time_sleep = mock.patch.object(time, 'sleep').start()
+        self._mock_time_sleep = mock.patch.object(time, 'sleep')
+        self.mock_time_sleep = self._mock_time_sleep.start()
+        self.addCleanup(self._stop_mocks)
 
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket')
+    def _stop_mocks(self):
+        self._mock_time_sleep.stop()
+
+    @mock.patch.object(prox_helpers, 'socket')
     def test___init__(self, mock_socket):
         expected = mock_socket.socket()
-        prox = ProxSocketHelper()
+        prox = prox_helpers.ProxSocketHelper()
         result = prox._sock
         self.assertEqual(result, expected)
 
     def test_connect(self):
         mock_sock = mock.MagicMock()
-        prox = ProxSocketHelper(mock_sock)
+        prox = prox_helpers.ProxSocketHelper(mock_sock)
         prox.connect('10.20.30.40', 23456)
-        self.assertEqual(mock_sock.connect.call_count, 1)
+        mock_sock.connect.assert_called_once()
 
     def test_get_sock(self):
         mock_sock = mock.MagicMock()
-        prox = ProxSocketHelper(mock_sock)
+        prox = prox_helpers.ProxSocketHelper(mock_sock)
         result = prox.get_socket()
         self.assertIs(result, mock_sock)
 
     # TODO(elfoley): Split this into three tests
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.select')
+    @mock.patch.object(prox_helpers, 'select')
     def test_get_data(self, mock_select):
         mock_select.select.side_effect = [[1], [0]]
         mock_socket = mock.MagicMock()
         mock_recv = mock_socket.recv()
         mock_recv.decode.return_value = ""
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         ret = prox.get_data()
         self.assertEqual(ret, "")
         self.assertEqual(len(prox._pkt_dumps), 0)
@@ -343,7 +336,7 @@ class TestProxSocketHelper(unittest.TestCase):
         self.assertEqual(len(prox._pkt_dumps), 3)
 
     def test__parse_socket_data_mixed_data(self):
-        prox = ProxSocketHelper(mock.MagicMock())
+        prox = prox_helpers.ProxSocketHelper(mock.MagicMock())
         ret, _ = prox._parse_socket_data(PACKET_DUMP_NON_1, False)
         self.assertEqual(ret, 'not_a_dump,1,2')
         self.assertEqual(len(prox._pkt_dumps), 0)
@@ -353,7 +346,7 @@ class TestProxSocketHelper(unittest.TestCase):
         self.assertEqual(len(prox._pkt_dumps), 1)
 
     def test__parse_socket_data_bad_data(self):
-        prox = ProxSocketHelper(mock.MagicMock())
+        prox = prox_helpers.ProxSocketHelper(mock.MagicMock())
         with self.assertRaises(ValueError):
             prox._parse_socket_data(PACKET_DUMP_BAD_1, False)
 
@@ -364,7 +357,7 @@ class TestProxSocketHelper(unittest.TestCase):
         self.assertEqual(ret, 'pktdump,3')
 
     def test__parse_socket_data_pkt_dump_only(self):
-        prox = ProxSocketHelper(mock.MagicMock())
+        prox = prox_helpers.ProxSocketHelper(mock.MagicMock())
         ret, _ = prox._parse_socket_data('', True)
         self.assertFalse(ret)
 
@@ -376,20 +369,20 @@ class TestProxSocketHelper(unittest.TestCase):
 
     def test_put_command(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.put_command("data")
         mock_socket.sendall.assert_called_once()
 
     def test_put_command_socket_error(self):
         mock_socket = mock.MagicMock()
         mock_socket.sendall.side_effect = OSError
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.put_command("data")
         mock_socket.sendall.assert_called_once()
 
     def test_get_packet_dump(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox._pkt_dumps = []
         self.assertIsNone(prox.get_packet_dump())
 
@@ -399,61 +392,61 @@ class TestProxSocketHelper(unittest.TestCase):
 
     def test_stop_all_reset(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.stop_all_reset()
         mock_socket.sendall.assert_called()
 
     def test_stop_all(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.stop_all()
         mock_socket.sendall.assert_called()
 
     def test_stop(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.stop([3, 4, 5], 16)
         mock_socket.sendall.assert_called()
 
     def test_start_all(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.start_all()
         mock_socket.sendall.assert_called()
 
     def test_start(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.start([3, 4, 5])
         mock_socket.sendall.assert_called()
 
     def test_reset_stats(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.reset_stats()
         mock_socket.sendall.assert_called()
 
     def test_set_pkt_size(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.set_pkt_size([3, 4, 5], 1024)
         self.assertEqual(mock_socket.sendall.call_count, 3)
 
     def test_set_value(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.set_value([3, 4, 5], 10, 20, 30)
         self.assertEqual(mock_socket.sendall.call_count, 3)
 
     def test_reset_values(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.reset_values([3, 4, 5])
         self.assertEqual(mock_socket.sendall.call_count, 3)
 
     def test_set_speed(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.set_speed([3, 4, 5], 1000)
         self.assertEqual(mock_socket.sendall.call_count, 3)
 
@@ -470,7 +463,7 @@ class TestProxSocketHelper(unittest.TestCase):
         ]
 
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.set_speed = set_speed = mock.MagicMock()
         prox.slope_speed(core_data, 5)
         self.assertEqual(set_speed.call_count, 20)
@@ -481,7 +474,7 @@ class TestProxSocketHelper(unittest.TestCase):
 
     def test_set_pps(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.set_pps([3, 4, 5], 1000, 512)
         self.assertEqual(mock_socket.sendall.call_count, 3)
 
@@ -495,7 +488,7 @@ class TestProxSocketHelper(unittest.TestCase):
         ]
 
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.get_data = mock.MagicMock(side_effect=latency_output)
 
         expected = (
@@ -518,7 +511,7 @@ class TestProxSocketHelper(unittest.TestCase):
 
     def test_get_all_tot_stats_error(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.get_data = mock.MagicMock(return_value='3,4,5')
         expected = [0, 0, 0, 0]
         result = prox.get_all_tot_stats()
@@ -526,7 +519,7 @@ class TestProxSocketHelper(unittest.TestCase):
 
     def test_get_all_tot_stats(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.get_data = mock.MagicMock(return_value='3,4,5,6')
         expected = 3, 4, 5, 6
         result = prox.get_all_tot_stats()
@@ -534,7 +527,7 @@ class TestProxSocketHelper(unittest.TestCase):
 
     def test_hz(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.get_data = mock.MagicMock(return_value='3,4,5,6')
         expected = 6
         result = prox.hz()
@@ -548,12 +541,37 @@ class TestProxSocketHelper(unittest.TestCase):
         ]
 
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.get_data = mock.MagicMock(side_effect=core_stats)
         expected = 21, 24, 27, 14
         result = prox.core_stats([3, 4, 5], 16)
         self.assertEqual(result, expected)
 
+    @mock.patch.object(prox_helpers.LOG, 'error')
+    def test_multi_port_stats(self, *args):
+        mock_socket = mock.MagicMock()
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
+        prox.get_data = mock.MagicMock(return_value='0,1,2,3,4,5;1,1,2,3,4,5')
+        expected = [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]]
+        result = prox.multi_port_stats([0, 1])
+        self.assertEqual(result, expected)
+
+        prox.get_data = mock.MagicMock(return_value='0,1,2,3,4,5;1,1,2,3,4,5')
+        result = prox.multi_port_stats([0])
+        expected = [0]
+        self.assertEqual(result, expected)
+
+        prox.get_data = mock.MagicMock(return_value='0,1,2,3;1,1,2,3,4,5')
+        result = prox.multi_port_stats([0, 1])
+        expected = [0] * 2
+        self.assertEqual(result, expected)
+
+        prox.get_data = mock.MagicMock(return_value='99,1,2,3,4,5;1,1,2,3,4,5')
+        expected = [0] * 2
+        result = prox.multi_port_stats([0, 1])
+        self.assertEqual(result, expected)
+
+
     def test_port_stats(self):
         port_stats = [
             ','.join(str(n) for n in range(3, 15)),
@@ -562,7 +580,7 @@ class TestProxSocketHelper(unittest.TestCase):
         ]
 
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.get_data = mock.MagicMock(side_effect=port_stats)
         expected = [16, 26, 36, 46, 56, 66, 76, 86, 96, 106, 116, 126]
         result = prox.port_stats([3, 4, 5])
@@ -579,7 +597,7 @@ class TestProxSocketHelper(unittest.TestCase):
         ]
 
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.get_data = mock.MagicMock(side_effect=get_data_output)
         expected = {
             'start_tot': start_tot,
@@ -592,7 +610,7 @@ class TestProxSocketHelper(unittest.TestCase):
 
     def test_tot_stats(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.get_data = mock.MagicMock(return_value='3,4,5,6')
         expected = 3, 4, 5
         result = prox.tot_stats()
@@ -600,7 +618,7 @@ class TestProxSocketHelper(unittest.TestCase):
 
     def test_tot_ierrors(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.get_data = mock.MagicMock(return_value='3,4,5,6')
         expected = 3, 3
         result = prox.tot_ierrors()
@@ -608,25 +626,25 @@ class TestProxSocketHelper(unittest.TestCase):
 
     def test_set_count(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.set_count(432, [3, 4, 5])
         self.assertEqual(mock_socket.sendall.call_count, 3)
 
     def test_dump_rx(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.dump_rx(3, 5, 8)
-        self.assertEqual(mock_socket.sendall.call_count, 1)
+        mock_socket.sendall.assert_called_once()
 
     def test_quit(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.quit()
         mock_socket.sendall.assert_called()
 
     def test_force_quit(self):
         mock_socket = mock.MagicMock()
-        prox = ProxSocketHelper(mock_socket)
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
         prox.force_quit()
         mock_socket.sendall.assert_called()
 
@@ -738,8 +756,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
     }
 
     def test_global_section(self):
-        setup_helper = ProxDpdkVnfSetupEnvHelper(mock.MagicMock(), mock.MagicMock(),
-                                                 mock.MagicMock())
+        setup_helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
 
         setup_helper._prox_config_data = [('a', [])]
 
@@ -787,8 +805,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         self.assertEqual(result, global_section[1])
 
     def test_find_in_section(self):
-        setup_helper = ProxDpdkVnfSetupEnvHelper(mock.MagicMock(), mock.MagicMock(),
-                                                 mock.MagicMock())
+        setup_helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
 
         setup_helper._prox_config_data = [
             ('global', [
@@ -841,44 +859,51 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         # empty string
         input_str = ''
         expected = ''
-        result = ProxDpdkVnfSetupEnvHelper._replace_quoted_with_value(input_str, 'cat')
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _replace_quoted_with_value(input_str, 'cat'))
         self.assertEqual(result, expected)
 
         # no quoted substring
         input_str = 'lion tiger bear'
         expected = 'lion tiger bear'
-        result = ProxDpdkVnfSetupEnvHelper._replace_quoted_with_value(input_str, 'cat')
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _replace_quoted_with_value(input_str, 'cat'))
         self.assertEqual(result, expected)
 
         # partially quoted substring
         input_str = 'lion "tiger bear'
         expected = 'lion "tiger bear'
-        result = ProxDpdkVnfSetupEnvHelper._replace_quoted_with_value(input_str, 'cat')
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _replace_quoted_with_value(input_str, 'cat'))
         self.assertEqual(result, expected)
 
         # one quoted substring
         input_str = 'lion "tiger" bear'
         expected = 'lion "cat" bear'
-        result = ProxDpdkVnfSetupEnvHelper._replace_quoted_with_value(input_str, 'cat')
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _replace_quoted_with_value(input_str, 'cat'))
         self.assertEqual(result, expected)
 
         # two quoted substrings
         input_str = 'lion "tiger" bear "shark" whale'
         expected = 'lion "cat" bear "shark" whale'
-        result = ProxDpdkVnfSetupEnvHelper._replace_quoted_with_value(input_str, 'cat')
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _replace_quoted_with_value(input_str, 'cat'))
         self.assertEqual(result, expected)
 
         # two quoted substrings, both replaced
         input_str = 'lion "tiger" bear "shark" whale'
         expected = 'lion "cat" bear "cat" whale'
-        result = ProxDpdkVnfSetupEnvHelper._replace_quoted_with_value(input_str, 'cat', 2)
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _replace_quoted_with_value(input_str, 'cat', 2))
         self.assertEqual(result, expected)
 
     def test__get_tx_port(self):
         # no data
         input_data = {'section1': []}
         expected = -1
-        result = ProxDpdkVnfSetupEnvHelper._get_tx_port('section1', input_data)
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _get_tx_port('section1', input_data))
         self.assertEqual(result, expected)
 
         # data for other section
@@ -890,7 +915,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
             ],
         }
         expected = -1
-        result = ProxDpdkVnfSetupEnvHelper._get_tx_port('section1', input_data)
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _get_tx_port('section1', input_data))
         self.assertEqual(result, expected)
 
         # data for section
@@ -899,7 +925,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
             ('tx port', '3'),
         ]
         expected = 3
-        result = ProxDpdkVnfSetupEnvHelper._get_tx_port('section1', input_data)
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _get_tx_port('section1', input_data))
         self.assertEqual(result, expected)
 
         # more data for section,
@@ -908,14 +935,16 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
             ('tx port', '1', 'and more', 234),
         ])
         expected = 1
-        result = ProxDpdkVnfSetupEnvHelper._get_tx_port('section1', input_data)
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  _get_tx_port('section1', input_data))
         self.assertEqual(result, expected)
 
     # TODO(elfoley): Split this into several smaller tests
     def test_write_prox_config(self):
         input_data = {}
         expected = ''
-        result = ProxDpdkVnfSetupEnvHelper.write_prox_config(input_data)
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  write_prox_config(input_data))
         self.assertEqual(result, expected)
 
         input_data = [
@@ -925,7 +954,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
             ],
         ]
         expected = '[section1]'
-        result = ProxDpdkVnfSetupEnvHelper.write_prox_config(input_data)
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  write_prox_config(input_data))
         self.assertEqual(result, expected)
 
         input_data = [
@@ -952,12 +982,13 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
             'key3=234',
             'key4=multi-line\n\tvalue',
         ])
-        result = ProxDpdkVnfSetupEnvHelper.write_prox_config(input_data)
+        result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+                  write_prox_config(input_data))
         self.assertEqual(result, expected)
 
     def test_prox_config_data(self):
-        setup_helper = ProxDpdkVnfSetupEnvHelper(mock.MagicMock(), mock.MagicMock(),
-                                                 mock.MagicMock())
+        setup_helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
 
         setup_helper.config_queue = config_queue = mock.MagicMock()
         config_queue.get.return_value = expected = [('s', [('a', 3), ('b', 45)])]
@@ -978,7 +1009,7 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
 
         vnfd_helper = mock.MagicMock()
         ssh_helper = mock.MagicMock()
-        scenario_helper = ScenarioHelper('vnf1')
+        scenario_helper = sample_vnf.ScenarioHelper('vnf1')
         scenario_helper.scenario_cfg = {
             'task_path': 'a/b',
             'options': {
@@ -986,7 +1017,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
             },
         }
 
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         helper.copy_to_target = mock.MagicMock(return_value='3')
         helper.generate_prox_config_file = mock.MagicMock(return_value='4')
         helper.upload_prox_config = mock.MagicMock(return_value='5')
@@ -1012,7 +1044,7 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         mock_find_path.side_effect = ['1', '2']
         vnfd_helper = mock.MagicMock()
         ssh_helper = mock.MagicMock()
-        scenario_helper = ScenarioHelper('vnf1')
+        scenario_helper = sample_vnf.ScenarioHelper('vnf1')
         scenario_helper.scenario_cfg = {
             'task_path': 'a/b',
             'options': {
@@ -1021,7 +1053,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         }
 
         vnfd_helper.port_pairs.all_ports = ['xe0', 'xe1', 'xe2', 'xe3']
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         helper.copy_to_target = mock.MagicMock(side_effect=['33', '34', '35'])
         helper.generate_prox_config_file = mock.MagicMock(return_value='44')
         helper.upload_prox_config = mock.MagicMock(return_value='55')
@@ -1047,7 +1080,7 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         mock_find_path.side_effect = ['1', '2'] + [str(i) for i in range(len(vnf1['prox_files']))]
         vnfd_helper = mock.MagicMock()
         ssh_helper = mock.MagicMock()
-        scenario_helper = ScenarioHelper('vnf1')
+        scenario_helper = sample_vnf.ScenarioHelper('vnf1')
         scenario_helper.scenario_cfg = {
             'task_path': 'a/b',
             'options': {
@@ -1055,7 +1088,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
             },
         }
 
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         helper.copy_to_target = mock.MagicMock(side_effect=['33', '34', '35'])
         helper.generate_prox_config_file = mock.MagicMock(return_value='44')
         helper.upload_prox_config = mock.MagicMock(return_value='55')
@@ -1084,7 +1118,7 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         vnfd_helper = mock.Mock()
         ssh_helper = mock.Mock()
         ssh_helper.join_bin_path.return_value = '/opt/nsb_bin/prox'
-        scenario_helper = ScenarioHelper('vnf1')
+        scenario_helper = sample_vnf.ScenarioHelper('vnf1')
         scenario_helper.scenario_cfg = {
             'task_path': 'a/b',
             'options': {
@@ -1095,8 +1129,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         expected = ("sudo bash -c 'cd /opt/nsb_bin; /opt/nsb_bin/prox -o cli "
                     "-f  -f /tmp/prox.cfg '")
 
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper,
-                                           scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         with mock.patch.object(helper, 'build_config_file') as mock_cfg_file:
             helper.remote_path = '/tmp/prox.cfg'
             prox_cmd = helper.build_config()
@@ -1108,7 +1142,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         ssh_helper = mock.MagicMock()
         scenario_helper = mock.MagicMock()
 
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         helper.additional_files = {"ipv4.lua": "/tmp/ipv4.lua"}
         res = helper._insert_additional_file('dofile("ipv4.lua")')
         self.assertEqual(res, 'dofile("/tmp/ipv4.lua")')
@@ -1124,11 +1159,12 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
 
         mock_parser_type.side_effect = init
 
-        vnfd_helper = VnfdHelper(self.VNFD0)
+        vnfd_helper = vnf_base.VnfdHelper(self.VNFD0)
         ssh_helper = mock.MagicMock()
         scenario_helper = mock.MagicMock()
 
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         helper.additional_files = {}
 
         expected = []
@@ -1213,7 +1249,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         ssh_helper = mock.MagicMock()
         scenario_helper = mock.MagicMock()
 
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         helper.additional_files = {}
         helper.remote_prox_file_name = 'remote'
         vnfd_helper.interfaces = [
@@ -1259,7 +1296,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         ssh_helper = mock.MagicMock()
         scenario_helper = mock.MagicMock()
 
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
 
         expected = 'a/b'
         result = helper.put_string_to_file('my long string', 'a/b')
@@ -1271,7 +1309,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         ssh_helper = mock.MagicMock()
         scenario_helper = mock.MagicMock()
 
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         expected = '/tmp/c'
         result = helper.copy_to_target('a/b', 'c')
         self.assertEqual(result, expected)
@@ -1282,7 +1321,8 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         ssh_helper = mock.MagicMock()
         scenario_helper = mock.MagicMock()
 
-        helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         helper.write_prox_config = mock.MagicMock(return_value='a long string')
         expected = '/tmp/a'
         result = helper.upload_prox_config('a', {})
@@ -1401,7 +1441,8 @@ class TestProxResourceHelper(unittest.TestCase):
             'nor here',
             'and still not',
         ]
-        result = ProxResourceHelper.find_pci('target', input_str_list)
+        result = prox_helpers.ProxResourceHelper.find_pci('target',
+                                                          input_str_list)
         self.assertFalse(result)
 
         input_str_list = [
@@ -1410,13 +1451,14 @@ class TestProxResourceHelper(unittest.TestCase):
             'this is a target',
             'did we miss it',
         ]
-        result = ProxResourceHelper.find_pci('target', input_str_list)
+        result = prox_helpers.ProxResourceHelper.find_pci('target',
+                                                          input_str_list)
         self.assertTrue(result)
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.RETRY_INTERVAL', 0)
     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.ProxSocketHelper')
     def test_sut(self, *args):
-        helper = ProxResourceHelper(mock.MagicMock())
+        helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
         self.assertIsNone(helper.client)
         result = helper.sut
         self.assertIsNotNone(result)
@@ -1427,7 +1469,7 @@ class TestProxResourceHelper(unittest.TestCase):
         setup_helper = mock.MagicMock()
         setup_helper.find_in_section.return_value = expected = 'prox type'
 
-        helper = ProxResourceHelper(setup_helper)
+        helper = prox_helpers.ProxResourceHelper(setup_helper)
 
         self.assertIsNone(helper._test_type)
         self.assertEqual(helper.test_type, expected)
@@ -1435,7 +1477,7 @@ class TestProxResourceHelper(unittest.TestCase):
         self.assertEqual(helper.test_type, expected)
 
     def test_collect_collectd_kpi(self):
-        helper = ProxResourceHelper(mock.MagicMock())
+        helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
         helper.resource = resource = mock.MagicMock()
 
         resource.check_if_system_agent_running.return_value = 0, '1234'
@@ -1447,7 +1489,7 @@ class TestProxResourceHelper(unittest.TestCase):
         self.assertDictEqual(result, expected)
 
     def test_collect_kpi(self):
-        helper = ProxResourceHelper(mock.MagicMock())
+        helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
         helper._queue = queue = mock.MagicMock()
         helper._result = {'z': 123}
         helper.resource = resource = mock.MagicMock()
@@ -1472,7 +1514,7 @@ class TestProxResourceHelper(unittest.TestCase):
         setup_helper = mock.MagicMock()
         setup_helper.vnfd_helper.interfaces = []
 
-        helper = ProxResourceHelper(setup_helper)
+        helper = prox_helpers.ProxResourceHelper(setup_helper)
 
         result = helper._connect()
         self.assertIs(result, client)
@@ -1484,41 +1526,41 @@ class TestProxResourceHelper(unittest.TestCase):
 
     def test_run_traffic(self):
         setup_helper = mock.MagicMock()
-        helper = ProxResourceHelper(setup_helper)
+        helper = prox_helpers.ProxResourceHelper(setup_helper)
         traffic_profile = mock.MagicMock(**{"done": True})
         helper.run_traffic(traffic_profile)
         self.assertEqual(helper._terminated.value, 1)
 
     def test__run_traffic_once(self):
         setup_helper = mock.MagicMock()
-        helper = ProxResourceHelper(setup_helper)
+        helper = prox_helpers.ProxResourceHelper(setup_helper)
         traffic_profile = mock.MagicMock(**{"done": True})
         helper._run_traffic_once(traffic_profile)
         self.assertEqual(helper._terminated.value, 1)
 
     def test_start_collect(self):
         setup_helper = mock.MagicMock()
-        helper = ProxResourceHelper(setup_helper)
+        helper = prox_helpers.ProxResourceHelper(setup_helper)
         helper.resource = resource = mock.MagicMock()
         self.assertIsNone(helper.start_collect())
         resource.start.assert_called_once()
 
     def test_terminate(self):
         setup_helper = mock.MagicMock()
-        helper = ProxResourceHelper(setup_helper)
+        helper = prox_helpers.ProxResourceHelper(setup_helper)
         with self.assertRaises(NotImplementedError):
             helper.terminate()
 
     def test_up_post(self):
         setup_helper = mock.MagicMock()
-        helper = ProxResourceHelper(setup_helper)
+        helper = prox_helpers.ProxResourceHelper(setup_helper)
         helper.client = expected = mock.MagicMock()
         result = helper.up_post()
         self.assertEqual(result, expected)
 
     def test_execute(self):
         setup_helper = mock.MagicMock()
-        helper = ProxResourceHelper(setup_helper)
+        helper = prox_helpers.ProxResourceHelper(setup_helper)
         helper.client = mock.MagicMock()
 
         expected = helper.client.my_command()
@@ -1540,34 +1582,35 @@ class TestProxDataHelper(unittest.TestCase):
         vnfd_helper.port_pairs.all_ports = list(range(4))
 
         sut = mock.MagicMock()
-        sut.port_stats.return_value = list(range(10))
+        sut.multi_port_stats.return_value = [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5],
+                                             [2, 1, 2, 3, 4, 5], [3, 1, 2, 3, 4, 5]]
 
-        data_helper = ProxDataHelper(
+        data_helper = prox_helpers.ProxDataHelper(
             vnfd_helper, sut, pkt_size, 25, None,
             constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
 
-        self.assertEqual(data_helper.rx_total, 6)
-        self.assertEqual(data_helper.tx_total, 7)
+        self.assertEqual(data_helper.rx_total, 4)
+        self.assertEqual(data_helper.tx_total, 8)
         self.assertEqual(data_helper.requested_pps, 6.25e6)
 
     def test_samples(self):
         vnfd_helper = mock.MagicMock()
-        vnfd_helper.port_pairs.all_ports = list(range(4))
-        vnfd_helper.ports_iter.return_value = [('xe1', 3), ('xe2', 7)]
+        vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
 
         sut = mock.MagicMock()
-        sut.port_stats.return_value = list(range(10))
+        sut.multi_port_stats.return_value = [[0, 1, 2, 3, 4, 5], [1, 11, 12, 3, 4, 5]]
 
-        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, None, None)
+        data_helper = prox_helpers.ProxDataHelper(
+            vnfd_helper, sut, None, None, None, None)
 
         expected = {
-            'xe1': {
-                'in_packets': 6,
-                'out_packets': 7,
+            'xe0': {
+                'in_packets': 1,
+                'out_packets': 2,
             },
-            'xe2': {
-                'in_packets': 6,
-                'out_packets': 7,
+            'xe1': {
+                'in_packets': 11,
+                'out_packets': 12,
             },
         }
         result = data_helper.samples
@@ -1581,17 +1624,19 @@ class TestProxDataHelper(unittest.TestCase):
         sut = mock.MagicMock()
         sut.port_stats.return_value = list(range(10))
 
-        data_helper = ProxDataHelper(vnfd_helper, sut, None, None,
+        data_helper = prox_helpers.ProxDataHelper(vnfd_helper, sut, None, None,
             5.4, constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
         data_helper._totals_and_pps = 12, 32, 4.5
         data_helper.tsc_hz = 9.8
-        data_helper.measured_stats = {'delta': TotStatsTuple(6.1, 6.2, 6.3, 6.4)}
+        data_helper.measured_stats = {
+            'delta': prox_helpers.TotStatsTuple(6.1, 6.2, 6.3, 6.4)}
         data_helper.latency = 7
 
         self.assertIsNone(data_helper.result_tuple)
         self.assertEqual(data_helper.line_speed, 10000000000)
 
-        expected = ProxTestDataTuple(5.4, 9.8, 6.1, 6.2, 6.3, 7, 12, 32, 4.5)
+        expected = prox_helpers.ProxTestDataTuple(
+            5.4, 9.8, 6.1, 6.2, 6.3, 7, 12, 32, 4.5)
         with data_helper:
             pass
 
@@ -1604,7 +1649,8 @@ class TestProxDataHelper(unittest.TestCase):
     def test___enter___negative(self):
         vnfd_helper = mock.MagicMock()
 
-        data_helper = ProxDataHelper(vnfd_helper, None, None, None, None, None)
+        data_helper = prox_helpers.ProxDataHelper(
+            vnfd_helper, None, None, None, None, None)
 
         vnfd_helper.port_pairs.all_ports = []
         with self.assertRaises(AssertionError):
@@ -1623,17 +1669,18 @@ class TestProxDataHelper(unittest.TestCase):
         start = (3, 4, 1, 2)
         end = (9, 7, 6, 8)
 
-        sut = ProxSocketHelper(mock.MagicMock())
+        sut = prox_helpers.ProxSocketHelper(mock.MagicMock())
         sut.get_all_tot_stats = mock.MagicMock(side_effect=[start, end])
 
-        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, 5.4, None)
+        data_helper = prox_helpers.ProxDataHelper(
+            vnfd_helper, sut, None, None, 5.4, None)
 
         self.assertIsNone(data_helper.measured_stats)
 
         expected = {
             'start_tot': start,
             'end_tot': end,
-            'delta': TotStatsTuple(6, 3, 5, 6),
+            'delta': prox_helpers.TotStatsTuple(6, 3, 5, 6),
         }
         with data_helper.measure_tot_stats():
             pass
@@ -1647,7 +1694,8 @@ class TestProxDataHelper(unittest.TestCase):
         sut = mock.MagicMock()
         sut.hz.return_value = '54.6'
 
-        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, None, None)
+        data_helper = prox_helpers.ProxDataHelper(
+            vnfd_helper, sut, None, None, None, None)
 
         self.assertIsNone(data_helper.tsc_hz)
 
@@ -1666,12 +1714,13 @@ class TestProxProfileHelper(unittest.TestCase):
         mock_type2.__prox_profile_type__ = 'my_type'
         mock_utils.itersubclasses.return_value = [mock_type1, mock_type2]
 
-        self.assertEqual(ProxProfileHelper.get_cls('my_type'), mock_type2)
+        self.assertEqual(prox_helpers.ProxProfileHelper.get_cls('my_type'),
+                         mock_type2)
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.utils')
     def test_get_cls_default(self, mock_utils):
         mock_utils.itersubclasses.return_value = []
-        ProxProfileHelper.get_cls('my_type')
+        prox_helpers.ProxProfileHelper.get_cls('my_type')
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.SocketTopology')
     def test_cpu_topology(self, mock_socket_topology):
@@ -1680,7 +1729,7 @@ class TestProxProfileHelper(unittest.TestCase):
         resource_helper = mock.MagicMock()
         resource_helper.setup_helper.ssh_helper.execute.return_value = 0, 'output', ''
 
-        helper = ProxProfileHelper(resource_helper)
+        helper = prox_helpers.ProxProfileHelper(resource_helper)
         self.assertIsNone(helper._cpu_topology)
         result = helper.cpu_topology
         self.assertEqual(result, 432)
@@ -1692,7 +1741,7 @@ class TestProxProfileHelper(unittest.TestCase):
         resource_helper = mock.MagicMock()
         resource_helper.setup_helper.prox_config_data = []
 
-        helper = ProxProfileHelper(resource_helper)
+        helper = prox_helpers.ProxProfileHelper(resource_helper)
         helper._cpu_topology = []
 
         expected = []
@@ -1720,7 +1769,7 @@ class TestProxProfileHelper(unittest.TestCase):
             ]),
         ]
 
-        helper = ProxProfileHelper(resource_helper)
+        helper = prox_helpers.ProxProfileHelper(resource_helper)
         helper._cpu_topology = {
             1: {
                 3: {
@@ -1750,7 +1799,7 @@ class TestProxProfileHelper(unittest.TestCase):
         resource_helper = mock.MagicMock()
         resource_helper.setup_helper.prox_config_data = []
 
-        helper = ProxProfileHelper(resource_helper)
+        helper = prox_helpers.ProxProfileHelper(resource_helper)
         helper._cpu_topology = []
 
         expected = []
@@ -1778,7 +1827,7 @@ class TestProxProfileHelper(unittest.TestCase):
             ]),
         ]
 
-        helper = ProxProfileHelper(resource_helper)
+        helper = prox_helpers.ProxProfileHelper(resource_helper)
         helper._cpu_topology = {
             1: {
                 3: {
@@ -1804,7 +1853,7 @@ class TestProxProfileHelper(unittest.TestCase):
         self.assertIs(result, helper.latency_cores)
 
     def test_all_rx_cores(self):
-        helper = ProxBngProfileHelper(mock.MagicMock())
+        helper = prox_helpers.ProxBngProfileHelper(mock.MagicMock())
         helper._latency_cores = expected = [3, 4, 6]
         helper._test_cores = [5, 2, 1]
 
@@ -1834,7 +1883,7 @@ class TestProxProfileHelper(unittest.TestCase):
             ]),
         ]
 
-        helper = ProxProfileHelper(resource_helper)
+        helper = prox_helpers.ProxProfileHelper(resource_helper)
         helper._cpu_topology = {
             0: {
                 1: {
@@ -1860,7 +1909,7 @@ class TestProxProfileHelper(unittest.TestCase):
         resource_helper = mock.MagicMock()
         resource_helper.setup_helper.vnfd_helper.interfaces = []
 
-        helper = ProxProfileHelper(resource_helper)
+        helper = prox_helpers.ProxProfileHelper(resource_helper)
         helper._latency_cores = []
 
         expected = []
@@ -1879,7 +1928,7 @@ class TestProxProfileHelper(unittest.TestCase):
         setup_helper = mock.MagicMock()
         setup_helper.vnfd_helper.interfaces = []
 
-        helper = ProxProfileHelper(setup_helper)
+        helper = prox_helpers.ProxProfileHelper(setup_helper)
         helper._cpu_topology = {
             0: {
                 1: {
@@ -1944,7 +1993,7 @@ class TestProxProfileHelper(unittest.TestCase):
         resource_helper.vnfd_helper.port_pairs.all_ports = list(range(2))
         resource_helper.sut.port_stats.return_value = list(range(10))
 
-        helper = ProxProfileHelper(resource_helper)
+        helper = prox_helpers.ProxProfileHelper(resource_helper)
 
         helper.run_test(120, 5, 6.5,
                         constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
@@ -1977,7 +2026,7 @@ class TestProxMplsProfileHelper(unittest.TestCase):
             ]),
         ]
 
-        helper = ProxMplsProfileHelper(resource_helper)
+        helper = prox_helpers.ProxMplsProfileHelper(resource_helper)
         helper._cpu_topology = {
             0: {
                 1: {
@@ -2004,7 +2053,7 @@ class TestProxMplsProfileHelper(unittest.TestCase):
 
     def test_traffic_context(self):
         setup_helper = mock.MagicMock()
-        helper = ProxMplsProfileHelper(setup_helper)
+        helper = prox_helpers.ProxMplsProfileHelper(setup_helper)
 
         with helper.traffic_context(120, 5.4):
             pass
@@ -2047,7 +2096,7 @@ class TestProxBngProfileHelper(unittest.TestCase):
             ]),
         ]
 
-        helper = ProxBngProfileHelper(resource_helper)
+        helper = prox_helpers.ProxBngProfileHelper(resource_helper)
         helper._cpu_topology = {
             0: {
                 1: {
@@ -2091,7 +2140,7 @@ class TestProxBngProfileHelper(unittest.TestCase):
         resource_helper.vnfd_helper.port_pairs.all_ports = list(range(2))
         resource_helper.sut.port_stats.return_value = list(range(10))
 
-        helper = ProxBngProfileHelper(resource_helper)
+        helper = prox_helpers.ProxBngProfileHelper(resource_helper)
 
         helper.run_test(120, 5, 6.5,
                         constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
@@ -2128,7 +2177,7 @@ class TestProxVpeProfileHelper(unittest.TestCase):
             ]),
         ]
 
-        helper = ProxVpeProfileHelper(resource_helper)
+        helper = prox_helpers.ProxVpeProfileHelper(resource_helper)
         helper._cpu_topology = {
             0: {
                 1: {
@@ -2175,7 +2224,7 @@ class TestProxVpeProfileHelper(unittest.TestCase):
             ]),
         ]
 
-        helper = ProxVpeProfileHelper(resource_helper)
+        helper = prox_helpers.ProxVpeProfileHelper(resource_helper)
         helper._port_list = {
             0: {
                 1: {
@@ -2209,7 +2258,7 @@ class TestProxVpeProfileHelper(unittest.TestCase):
         resource_helper.vnfd_helper.port_pairs.all_ports = list(range(2))
         resource_helper.sut.port_stats.return_value = list(range(10))
 
-        helper = ProxVpeProfileHelper(resource_helper)
+        helper = prox_helpers.ProxVpeProfileHelper(resource_helper)
 
         helper.run_test(120, 5, 6.5)
         helper.run_test(-1000, 5, 6.5)  # negative pkt_size is the only way to make ratio > 1
@@ -2242,7 +2291,7 @@ class TestProxlwAFTRProfileHelper(unittest.TestCase):
             ]),
         ]
 
-        helper = ProxlwAFTRProfileHelper(resource_helper)
+        helper = prox_helpers.ProxlwAFTRProfileHelper(resource_helper)
         helper._cpu_topology = {
             0: {
                 1: {
@@ -2289,7 +2338,7 @@ class TestProxlwAFTRProfileHelper(unittest.TestCase):
             ]),
         ]
 
-        helper = ProxlwAFTRProfileHelper(resource_helper)
+        helper = prox_helpers.ProxlwAFTRProfileHelper(resource_helper)
         helper._port_list = {
             0: {
                 1: {
@@ -2323,7 +2372,7 @@ class TestProxlwAFTRProfileHelper(unittest.TestCase):
         resource_helper.vnfd_helper.port_pairs.all_ports = list(range(2))
         resource_helper.sut.port_stats.return_value = list(range(10))
 
-        helper = ProxlwAFTRProfileHelper(resource_helper)
+        helper = prox_helpers.ProxlwAFTRProfileHelper(resource_helper)
 
         helper.run_test(120, 5, 6.5)
         helper.run_test(-1000, 5, 6.5)  # negative pkt_size is the only way to make ratio > 1
index fa2d462..678e580 100644 (file)
@@ -20,6 +20,7 @@ import mock
 from copy import deepcopy
 
 from yardstick.tests import STL_MOCKS
+from yardstick.benchmark.contexts import base as ctx_base
 
 
 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
@@ -29,7 +30,7 @@ stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
 stl_patch.start()
 
 if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.prox_vnf import ProxApproxVnf
+    from yardstick.network_services.vnf_generic.vnf import prox_vnf
     from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
 
 
@@ -187,7 +188,7 @@ class TestProxApproxVnf(unittest.TestCase):
                 'interfaces': {
                     'xe0': {
                         'local_iface_name': 'ens513f0',
-                        'vld_id': ProxApproxVnf.DOWNLINK,
+                        'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK,
                         'netmask': '255.255.255.0',
                         'local_ip': '152.16.40.20',
                         'dst_mac': '00:00:00:00:00:01',
@@ -221,7 +222,7 @@ class TestProxApproxVnf(unittest.TestCase):
                 'interfaces': {
                     'xe0': {
                         'local_iface_name': 'ens785f0',
-                        'vld_id': ProxApproxVnf.UPLINK,
+                        'vld_id': prox_vnf.ProxApproxVnf.UPLINK,
                         'netmask': '255.255.255.0',
                         'local_ip': '152.16.100.20',
                         'dst_mac': '00:00:00:00:00:02',
@@ -252,7 +253,7 @@ class TestProxApproxVnf(unittest.TestCase):
                 'interfaces': {
                     'xe0': {
                         'local_iface_name': 'ens786f0',
-                        'vld_id': ProxApproxVnf.UPLINK,
+                        'vld_id': prox_vnf.ProxApproxVnf.UPLINK,
                         'netmask': '255.255.255.0',
                         'local_ip': '152.16.100.19',
                         'dst_mac': '00:00:00:00:00:04',
@@ -264,7 +265,7 @@ class TestProxApproxVnf(unittest.TestCase):
                     },
                     'xe1': {
                         'local_iface_name': 'ens786f1',
-                        'vld_id': ProxApproxVnf.DOWNLINK,
+                        'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK,
                         'netmask': '255.255.255.0',
                         'local_ip': '152.16.40.19',
                         'dst_mac': '00:00:00:00:00:03',
@@ -316,16 +317,21 @@ class TestProxApproxVnf(unittest.TestCase):
     @mock.patch(SSH_HELPER)
     def test___init__(self, ssh, *args):
         mock_ssh(ssh)
-        prox_approx_vnf = ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
         self.assertIsNone(prox_approx_vnf._vnf_process)
 
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     @mock.patch(SSH_HELPER)
     def test_collect_kpi_no_client(self, ssh, *args):
         mock_ssh(ssh)
 
-        prox_approx_vnf = ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {prox_approx_vnf.name: "mock"}
+        }
         prox_approx_vnf.resource_helper = None
         expected = {
+            'physical_node': 'mock_node',
             'packets_in': 0,
             'packets_dropped': 0,
             'packets_fwd': 0,
@@ -334,21 +340,27 @@ class TestProxApproxVnf(unittest.TestCase):
         result = prox_approx_vnf.collect_kpi()
         self.assertEqual(result, expected)
 
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     @mock.patch(SSH_HELPER)
     def test_collect_kpi(self, ssh, *args):
         mock_ssh(ssh)
 
         resource_helper = mock.MagicMock()
-        resource_helper.execute.return_value = list(range(12))
+        resource_helper.execute.return_value = [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5],
+                                                [2, 1, 2, 3, 4, 5], [3, 1, 2, 3, 4, 5]]
         resource_helper.collect_collectd_kpi.return_value = {'core': {'result': 234}}
 
-        prox_approx_vnf = ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {prox_approx_vnf.name: "mock"}
+        }
         prox_approx_vnf.resource_helper = resource_helper
 
         expected = {
-            'packets_in': 6,
-            'packets_dropped': 1,
-            'packets_fwd': 7,
+            'physical_node': 'mock_node',
+            'packets_in': 4,
+            'packets_dropped': 4,
+            'packets_fwd': 8,
             'collect_stats': {'core': {'result': 234}},
         }
         result = prox_approx_vnf.collect_kpi()
@@ -358,13 +370,16 @@ class TestProxApproxVnf(unittest.TestCase):
         self.assertNotEqual(result['packets_fwd'], 0)
         self.assertNotEqual(result['packets_fwd'], 0)
 
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     @mock.patch(SSH_HELPER)
     def test_collect_kpi_error(self, ssh, *args):
         mock_ssh(ssh)
 
         resource_helper = mock.MagicMock()
-
-        prox_approx_vnf = ProxApproxVnf(NAME, deepcopy(self.VNFD0))
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, deepcopy(self.VNFD0))
+        prox_approx_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {prox_approx_vnf.name: "mock"}
+        }
         prox_approx_vnf.resource_helper = resource_helper
         prox_approx_vnf.vnfd_helper['vdu'][0]['external-interface'] = []
         prox_approx_vnf.vnfd_helper.port_pairs.interfaces = []
@@ -384,7 +399,7 @@ class TestProxApproxVnf(unittest.TestCase):
     def test_run_prox(self, ssh, *_):
         mock_ssh(ssh)
 
-        prox_approx_vnf = ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
         prox_approx_vnf.scenario_helper.scenario_cfg = self.SCENARIO_CFG
         prox_approx_vnf.ssh_helper.join_bin_path.return_value = '/tool_path12/tool_file34'
         prox_approx_vnf.setup_helper.remote_path = 'configs/file56.cfg'
@@ -398,7 +413,7 @@ class TestProxApproxVnf(unittest.TestCase):
 
     @mock.patch(SSH_HELPER)
     def bad_test_instantiate(self, *args):
-        prox_approx_vnf = ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
         prox_approx_vnf.scenario_helper = mock.MagicMock()
         prox_approx_vnf.setup_helper = mock.MagicMock()
         # we can't mock super
@@ -408,7 +423,7 @@ class TestProxApproxVnf(unittest.TestCase):
     @mock.patch(SSH_HELPER)
     def test_wait_for_instantiate_panic(self, ssh, *args):
         mock_ssh(ssh, exec_result=(1, "", ""))
-        prox_approx_vnf = ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
         prox_approx_vnf._vnf_process = mock.MagicMock(**{"is_alive.return_value": True})
         prox_approx_vnf._run_prox = mock.Mock(return_value=0)
         prox_approx_vnf.WAIT_TIME = 0
@@ -420,7 +435,7 @@ class TestProxApproxVnf(unittest.TestCase):
     @mock.patch(SSH_HELPER)
     def test_terminate(self, ssh, *args):
         mock_ssh(ssh)
-        prox_approx_vnf = ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
         prox_approx_vnf._vnf_process = mock.MagicMock()
         prox_approx_vnf._vnf_process.terminate = mock.Mock()
         prox_approx_vnf.ssh_helper = mock.MagicMock()
@@ -432,16 +447,16 @@ class TestProxApproxVnf(unittest.TestCase):
     @mock.patch(SSH_HELPER)
     def test__vnf_up_post(self, ssh, *args):
         mock_ssh(ssh)
-        prox_approx_vnf = ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
         prox_approx_vnf.resource_helper = resource_helper = mock.Mock()
 
         prox_approx_vnf._vnf_up_post()
-        self.assertEqual(resource_helper.up_post.call_count, 1)
+        resource_helper.up_post.assert_called_once()
 
     @mock.patch(SSH_HELPER)
     def test_vnf_execute_oserror(self, ssh, *args):
         mock_ssh(ssh)
-        prox_approx_vnf = ProxApproxVnf(NAME, self.VNFD0)
+        prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
         prox_approx_vnf.resource_helper = resource_helper = mock.Mock()
 
         resource_helper.execute.side_effect = OSError(errno.EPIPE, "")
index 5574c67..edd0ff7 100644 (file)
@@ -18,6 +18,7 @@ import mock
 
 from yardstick.tests import STL_MOCKS
 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+from yardstick.benchmark.contexts import base as ctx_base
 
 
 STLClient = mock.MagicMock()
@@ -214,15 +215,25 @@ class TestRouterVNF(unittest.TestCase):
         stats = RouterVNF.get_stats(self.IP_SHOW_STATS_OUTPUT)
         self.assertDictEqual(stats, self.STATS)
 
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
     @mock.patch(SSH_HELPER)
-    def test_collect_kpi(self, ssh, _):
+    def test_collect_kpi(self, ssh, *args):
         m = mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         router_vnf = RouterVNF(name, vnfd)
+        router_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {router_vnf.name: "mock"}
+        }
         router_vnf.ssh_helper = m
-        result = {'packets_dropped': 0, 'packets_fwd': 0, 'packets_in': 0, 'link_stats': {}}
+        result = {
+            'physical_node': 'mock_node',
+            'packets_dropped': 0,
+            'packets_fwd': 0,
+            'packets_in': 0,
+            'link_stats': {}
+        }
         self.assertEqual(result, router_vnf.collect_kpi())
 
     @mock.patch(SSH_HELPER)
@@ -235,9 +246,9 @@ class TestRouterVNF(unittest.TestCase):
         router_vnf._run()
         router_vnf.ssh_helper.drop_connection.assert_called_once()
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.router_vnf.Context")
+    @mock.patch.object(ctx_base, 'Context')
     @mock.patch(SSH_HELPER)
-    def test_instantiate(self, ssh, _):
+    def test_instantiate(self, ssh, *args):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
index b46ba65..48ae3b5 100644 (file)
@@ -11,7 +11,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
 
 from copy import deepcopy
 
@@ -19,37 +18,29 @@ import unittest
 import mock
 import six
 
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
-from yardstick.tests import STL_MOCKS
-from yardstick.benchmark.contexts.base import Context
 from yardstick.common import exceptions as y_exceptions
 from yardstick.common import utils
 from yardstick.network_services.nfvi.resource import ResourceProfile
 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
-
-
-class MockError(BaseException):
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFDeployHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SetupEnvHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
+from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base
+from yardstick.benchmark.contexts import base as ctx_base
+
+
+class MockError(Exception):
     pass
 
 
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf import sample_vnf
-    from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFDeployHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import SetupEnvHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
-
-
 class TestVnfSshHelper(unittest.TestCase):
 
     VNFD_0 = {
@@ -192,12 +183,12 @@ class TestVnfSshHelper(unittest.TestCase):
         self.assertFalse(ssh_helper.is_connected)
         cfg_file = ssh_helper.upload_config_file('my/prefix', 'my content')
         self.assertTrue(ssh_helper.is_connected)
-        self.assertEqual(mock_paramiko.SSHClient.call_count, 1)
+        mock_paramiko.SSHClient.assert_called_once()
         self.assertTrue(cfg_file.startswith('/tmp'))
 
         cfg_file = ssh_helper.upload_config_file('/my/prefix', 'my content')
         self.assertTrue(ssh_helper.is_connected)
-        self.assertEqual(mock_paramiko.SSHClient.call_count, 1)
+        mock_paramiko.SSHClient.assert_called_once()
         self.assertEqual(cfg_file, '/my/prefix')
 
     def test_join_bin_path(self):
@@ -234,17 +225,17 @@ class TestVnfSshHelper(unittest.TestCase):
         self.assertFalse(ssh_helper.is_connected)
         ssh_helper.provision_tool()
         self.assertTrue(ssh_helper.is_connected)
-        self.assertEqual(mock_paramiko.SSHClient.call_count, 1)
-        self.assertEqual(mock_provision_tool.call_count, 1)
+        mock_paramiko.SSHClient.assert_called_once()
+        mock_provision_tool.assert_called_once()
 
         ssh_helper.provision_tool(tool_file='my_tool.sh')
         self.assertTrue(ssh_helper.is_connected)
-        self.assertEqual(mock_paramiko.SSHClient.call_count, 1)
+        mock_paramiko.SSHClient.assert_called_once()
         self.assertEqual(mock_provision_tool.call_count, 2)
 
         ssh_helper.provision_tool('tool_path', 'my_tool.sh')
         self.assertTrue(ssh_helper.is_connected)
-        self.assertEqual(mock_paramiko.SSHClient.call_count, 1)
+        mock_paramiko.SSHClient.assert_called_once()
         self.assertEqual(mock_provision_tool.call_count, 3)
 
 
@@ -572,6 +563,7 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         scenario_helper.vnf_cfg = {}
+        scenario_helper.options = {}
         scenario_helper.all_options = {}
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
 
@@ -579,10 +571,11 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
         result = dpdk_setup_helper.build_config()
         self.assertEqual(result, expected)
         self.assertGreaterEqual(ssh_helper.upload_config_file.call_count, 2)
-        self.assertGreaterEqual(mock_find.call_count, 1)
-        self.assertGreaterEqual(mock_multi_port_config.generate_config.call_count, 1)
-        self.assertGreaterEqual(mock_multi_port_config.generate_script.call_count, 1)
+        mock_find.assert_called()
+        mock_multi_port_config.generate_config.assert_called()
+        mock_multi_port_config.generate_script.assert_called()
 
+        scenario_helper.options = {'rules': 'fake_file'}
         scenario_helper.vnf_cfg = {'file': 'fake_file'}
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
         mock_open_rf.side_effect = mock.mock_open(read_data='fake_data')
@@ -590,12 +583,12 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
 
         result = dpdk_setup_helper.build_config()
 
-        mock_open_rf.assert_called_once()
+        mock_open_rf.assert_called()
         self.assertEqual(result, expected)
         self.assertGreaterEqual(ssh_helper.upload_config_file.call_count, 2)
-        self.assertGreaterEqual(mock_find.call_count, 1)
-        self.assertGreaterEqual(mock_multi_port_config.generate_config.call_count, 1)
-        self.assertGreaterEqual(mock_multi_port_config.generate_script.call_count, 1)
+        mock_find.assert_called()
+        mock_multi_port_config.generate_config.assert_called()
+        mock_multi_port_config.generate_script.assert_called()
 
     def test__build_pipeline_kwargs(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
@@ -1001,203 +994,69 @@ class TestClientResourceHelper(unittest.TestCase):
     }
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.STLError',
-                new_callable=lambda: MockError)
-    def test_get_stats_not_connected(self, mock_state_error, *args):
+    @mock.patch.object(sample_vnf, 'STLError', new_callable=lambda: MockError)
+    def test_get_stats_not_connected(self, mock_stl_error, *args):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
-        client_resource_helper.client = mock.MagicMock()
-        client_resource_helper.client.get_stats.side_effect = mock_state_error
+        client_resource_helper.client = mock.Mock()
+        client_resource_helper.client.get_stats.side_effect = mock_stl_error
 
         self.assertEqual(client_resource_helper.get_stats(), {})
-        self.assertEqual(client_resource_helper.client.get_stats.call_count, 1)
-
-    def test_generate_samples(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
-        client_resource_helper.client = mock.MagicMock()
-        client_resource_helper.client.get_stats.return_value = {
-            0: {
-                'rx_pps': 5.5,
-                'tx_pps': 4.9,
-                'rx_bps': 234.78,
-                'tx_bps': 243.11,
-                'ipackets': 34251,
-                'opackets': 52342,
-            },
-            1: {
-                'tx_pps': 5.9,
-                'rx_bps': 434.78,
-                'opackets': 48791,
-            },
-        }
-
-        expected = {
-            'xe0': {
-                "rx_throughput_fps": 5.5,
-                "tx_throughput_fps": 4.9,
-                "rx_throughput_mbps": 234.78,
-                "tx_throughput_mbps": 243.11,
-                "in_packets": 34251,
-                "out_packets": 52342,
-            },
-            'xe1': {
-                "rx_throughput_fps": 0.0,
-                "tx_throughput_fps": 5.9,
-                "rx_throughput_mbps": 434.78,
-                "tx_throughput_mbps": 0.0,
-                "in_packets": 0,
-                "out_packets": 48791,
-            },
-        }
-        ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
-        result = client_resource_helper.generate_samples(ports)
-        self.assertDictEqual(result, expected)
-
-    def test_generate_samples_with_key(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
-        client_resource_helper.client = mock.MagicMock()
-        client_resource_helper.client.get_stats.return_value = {
-            'key_name': 'key_value',
-            0: {
-                'rx_pps': 5.5,
-                'tx_pps': 4.9,
-                'rx_bps': 234.78,
-                'tx_bps': 243.11,
-                'ipackets': 34251,
-                'opackets': 52342,
-            },
-            1: {
-                'tx_pps': 5.9,
-                'rx_bps': 434.78,
-                'opackets': 48791,
-            },
-        }
-
-        expected = {
-            'xe0': {
-                'key_name': 'key_value',
-                "rx_throughput_fps": 5.5,
-                "tx_throughput_fps": 4.9,
-                "rx_throughput_mbps": 234.78,
-                "tx_throughput_mbps": 243.11,
-                "in_packets": 34251,
-                "out_packets": 52342,
-            },
-            'xe1': {
-                'key_name': 'key_value',
-                "rx_throughput_fps": 0.0,
-                "tx_throughput_fps": 5.9,
-                "rx_throughput_mbps": 434.78,
-                "tx_throughput_mbps": 0.0,
-                "in_packets": 0,
-                "out_packets": 48791,
-            },
-        }
-        ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
-        result = client_resource_helper.generate_samples(ports, 'key_name')
-        self.assertDictEqual(result, expected)
-
-    def test_generate_samples_with_key_and_default(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
-        client_resource_helper.client = mock.MagicMock()
-        client_resource_helper.client.get_stats.return_value = {
-            0: {
-                'rx_pps': 5.5,
-                'tx_pps': 4.9,
-                'rx_bps': 234.78,
-                'tx_bps': 243.11,
-                'ipackets': 34251,
-                'opackets': 52342,
-            },
-            1: {
-                'tx_pps': 5.9,
-                'rx_bps': 434.78,
-                'opackets': 48791,
-            },
-        }
-
-        expected = {
-            'xe0': {
-                'key_name': 'default',
-                "rx_throughput_fps": 5.5,
-                "tx_throughput_fps": 4.9,
-                "rx_throughput_mbps": 234.78,
-                "tx_throughput_mbps": 243.11,
-                "in_packets": 34251,
-                "out_packets": 52342,
-            },
-            'xe1': {
-                'key_name': 'default',
-                "rx_throughput_fps": 0.0,
-                "tx_throughput_fps": 5.9,
-                "rx_throughput_mbps": 434.78,
-                "tx_throughput_mbps": 0.0,
-                "in_packets": 0,
-                "out_packets": 48791,
-            },
-        }
-        ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
-        result = client_resource_helper.generate_samples(ports, 'key_name', 'default')
-        self.assertDictEqual(result, expected)
+        client_resource_helper.client.get_stats.assert_called_once()
 
     def test_clear_stats(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client_resource_helper.client = mock.Mock()
 
         self.assertIsNone(client_resource_helper.clear_stats())
-        self.assertEqual(client_resource_helper.client.clear_stats.call_count, 1)
+        self.assertEqual(
+            client_resource_helper.client.clear_stats.call_count, 1)
 
     def test_clear_stats_of_ports(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client_resource_helper.client = mock.Mock()
 
         self.assertIsNone(client_resource_helper.clear_stats([3, 4]))
-        self.assertEqual(client_resource_helper.client.clear_stats.call_count, 1)
+        self.assertEqual(
+            client_resource_helper.client.clear_stats.call_count, 1)
 
     def test_start(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client_resource_helper.client = mock.Mock()
 
         self.assertIsNone(client_resource_helper.start())
-        self.assertEqual(client_resource_helper.client.start.call_count, 1)
+        client_resource_helper.client.start.assert_called_once()
 
     def test_start_ports(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client_resource_helper.client = mock.Mock()
 
         self.assertIsNone(client_resource_helper.start([3, 4]))
-        self.assertEqual(client_resource_helper.client.start.call_count, 1)
+        client_resource_helper.client.start.assert_called_once()
 
     def test_collect_kpi_with_queue(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
@@ -1219,20 +1078,69 @@ class TestClientResourceHelper(unittest.TestCase):
         self.assertDictEqual(result, expected)
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.STLError',
-                new_callable=lambda: MockError)
-    def test__connect_with_failures(self, mock_error, *args):
+    @mock.patch.object(sample_vnf, 'STLError')
+    def test__connect_with_failures(self, mock_stl_error, *args):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client = mock.MagicMock()
-        client.connect.side_effect = mock_error
+        client.connect.side_effect = mock_stl_error(msg='msg')
 
         self.assertIs(client_resource_helper._connect(client), client)
 
+    @mock.patch.object(ClientResourceHelper, '_build_ports')
+    @mock.patch.object(ClientResourceHelper, '_run_traffic_once')
+    def test_run_traffic(self, mock_run_traffic_once, mock_build_ports):
+        client_resource_helper = ClientResourceHelper(mock.Mock())
+        client = mock.Mock()
+        traffic_profile = mock.Mock()
+        mq_producer = mock.Mock()
+        with mock.patch.object(client_resource_helper, '_connect') \
+                as mock_connect, \
+                mock.patch.object(client_resource_helper, '_terminated') \
+                as mock_terminated:
+            mock_connect.return_value = client
+            type(mock_terminated).value = mock.PropertyMock(
+                side_effect=[0, 1, lambda x: x])
+            client_resource_helper.run_traffic(traffic_profile, mq_producer)
+
+        mock_build_ports.assert_called_once()
+        traffic_profile.register_generator.assert_called_once()
+        mq_producer.tg_method_started.assert_called_once()
+        mq_producer.tg_method_finished.assert_called_once()
+        mq_producer.tg_method_iteration.assert_called_once_with(1)
+        mock_run_traffic_once.assert_called_once_with(traffic_profile)
+
+    @mock.patch.object(ClientResourceHelper, '_build_ports')
+    @mock.patch.object(ClientResourceHelper, '_run_traffic_once',
+                       side_effect=Exception)
+    def test_run_traffic_exception(self, mock_run_traffic_once,
+                                   mock_build_ports):
+        client_resource_helper = ClientResourceHelper(mock.Mock())
+        client = mock.Mock()
+        traffic_profile = mock.Mock()
+        mq_producer = mock.Mock()
+        with mock.patch.object(client_resource_helper, '_connect') \
+                as mock_connect, \
+                mock.patch.object(client_resource_helper, '_terminated') \
+                as mock_terminated:
+            mock_connect.return_value = client
+            type(mock_terminated).value = mock.PropertyMock(return_value=0)
+            mq_producer.reset_mock()
+            # NOTE(ralonsoh): "trex_stl_exceptions.STLError" is mocked
+            with self.assertRaises(Exception):
+                client_resource_helper.run_traffic(traffic_profile,
+                                                   mq_producer)
+
+        mock_build_ports.assert_called_once()
+        traffic_profile.register_generator.assert_called_once()
+        mock_run_traffic_once.assert_called_once_with(traffic_profile)
+        mq_producer.tg_method_started.assert_called_once()
+        mq_producer.tg_method_finished.assert_not_called()
+        mq_producer.tg_method_iteration.assert_not_called()
+
 
 class TestRfc2544ResourceHelper(unittest.TestCase):
 
@@ -1405,7 +1313,7 @@ class TestSampleVNFDeployHelper(unittest.TestCase):
         self.assertIsNone(sample_vnf_deploy_helper.deploy_vnfs('name1'))
         sample_vnf_deploy_helper.DISABLE_DEPLOY = True
         self.assertEqual(ssh_helper.execute.call_count, 5)
-        self.assertEqual(ssh_helper.put.call_count, 1)
+        ssh_helper.put.assert_called_once()
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
     @mock.patch('subprocess.check_output')
@@ -1420,7 +1328,7 @@ class TestSampleVNFDeployHelper(unittest.TestCase):
 
         self.assertIsNone(sample_vnf_deploy_helper.deploy_vnfs('name1'))
         self.assertEqual(ssh_helper.execute.call_count, 5)
-        self.assertEqual(ssh_helper.put.call_count, 1)
+        ssh_helper.put.assert_called_once()
 
     @mock.patch('subprocess.check_output')
     def test_deploy_vnfs_early_success(self, *args):
@@ -1433,8 +1341,8 @@ class TestSampleVNFDeployHelper(unittest.TestCase):
         sample_vnf_deploy_helper.DISABLE_DEPLOY = False
 
         self.assertIsNone(sample_vnf_deploy_helper.deploy_vnfs('name1'))
-        self.assertEqual(ssh_helper.execute.call_count, 1)
-        self.assertEqual(ssh_helper.put.call_count, 0)
+        ssh_helper.execute.assert_called_once()
+        ssh_helper.put.assert_not_called()
 
 
 class TestScenarioHelper(unittest.TestCase):
@@ -1676,33 +1584,20 @@ class TestSampleVnf(unittest.TestCase):
         self.assertIsNotNone(sample_vnf.queue_wrapper)
         self.assertIsNotNone(sample_vnf._vnf_process)
 
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
     @mock.patch("yardstick.ssh.SSH")
-    def test_instantiate(self, ssh):
-        mock_ssh(ssh)
-
+    def test_instantiate(self, ssh, *args):
+        test_base.mock_ssh(ssh)
         nodes = {
             'vnf1': 'name1',
             'vnf2': 'name2',
         }
 
-        context1 = mock.Mock()
-        context1._get_server.return_value = None
-        context2 = mock.Mock()
-        context2._get_server.return_value = context2
-
-        try:
-            Context.list.clear()
-        except AttributeError:
-            # clear() but works in Py2.7
-            Context.list[:] = []
-
-        Context.list.extend([
-            context1,
-            context2,
-        ])
-
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         sample_vnf = SampleVNF('vnf1', vnfd)
+        sample_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {sample_vnf.name: 'mock'}
+        }
         sample_vnf.APP_NAME = 'sample1'
         sample_vnf._start_server = mock.Mock(return_value=0)
         sample_vnf._vnf_process = mock.MagicMock()
@@ -1715,7 +1610,6 @@ class TestSampleVnf(unittest.TestCase):
         }
 
         self.assertIsNone(sample_vnf.instantiate(scenario_cfg, {}))
-        self.assertEqual(sample_vnf.nfvi_context, context2)
 
     def test__update_collectd_options(self):
         scenario_cfg = {'options':
@@ -1778,7 +1672,7 @@ class TestSampleVnf(unittest.TestCase):
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
     @mock.patch("yardstick.ssh.SSH")
     def test_wait_for_instantiate_empty_queue(self, ssh, *args):
-        mock_ssh(ssh, exec_result=(1, "", ""))
+        test_base.mock_ssh(ssh, exec_result=(1, "", ""))
 
         queue_size_list = [
             0,
@@ -1852,9 +1746,13 @@ class TestSampleVnf(unittest.TestCase):
 
         self.assertEqual(sample_vnf.get_stats(), 'the stats')
 
-    def test_collect_kpi(self):
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+    def test_collect_kpi(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         sample_vnf = SampleVNF('vnf1', vnfd)
+        sample_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {sample_vnf.name: "mock"}
+        }
         sample_vnf.APP_NAME = 'sample1'
         sample_vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)'
         sample_vnf.COLLECT_MAP = {
@@ -1871,18 +1769,24 @@ class TestSampleVnf(unittest.TestCase):
             'k2': 34,
             'k3': 91,
             'collect_stats': {},
+            'physical_node': 'mock_node'
         }
         result = sample_vnf.collect_kpi()
         self.assertDictEqual(result, expected)
 
-    def test_collect_kpi_default(self):
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+    def test_collect_kpi_default(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         sample_vnf = SampleVNF('vnf1', vnfd)
+        sample_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {sample_vnf.name: "mock"}
+        }
         sample_vnf.APP_NAME = 'sample1'
         sample_vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)'
         sample_vnf.get_stats = mock.Mock(return_value='')
 
         expected = {
+            'physical_node': 'mock_node',
             'packets_in': 0,
             'packets_fwd': 0,
             'packets_dropped': 0,
index 5bebbbf..66f9e93 100644 (file)
 # 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.
-#
 
 import subprocess
 
 import mock
-import unittest
 import six
+import unittest
 
-from yardstick.tests import STL_MOCKS
 from yardstick import ssh
+from yardstick.benchmark.contexts import base as ctx_base
 from yardstick.common import utils
-
-
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.tg_ixload import IxLoadTrafficGen
-    from yardstick.network_services.vnf_generic.vnf.tg_ixload import IxLoadResourceHelper
-    from yardstick.network_services.traffic_profile.base import TrafficProfile
+from yardstick.network_services.vnf_generic.vnf import tg_ixload
+from yardstick.network_services.traffic_profile.base import TrafficProfile
 
 
 NAME = "tg__1"
@@ -118,146 +109,127 @@ class TestIxLoadTrafficGen(unittest.TestCase):
     def setUp(self):
         self._mock_call = mock.patch.object(subprocess, "call")
         self.mock_call = self._mock_call.start()
-        self._mock_open = mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.open")
+        self._mock_open = mock.patch.object(tg_ixload, 'open')
         self.mock_open = self._mock_open.start()
-
         self.addCleanup(self._stop_mock)
 
     def _stop_mock(self):
         self._mock_call.stop()
         self._mock_open.stop()
 
-    def test___init__(self):
-        with mock.patch("yardstick.ssh.SSH") as ssh:
-            ssh_mock = mock.Mock(autospec=ssh.SSH)
-            ssh_mock.execute = \
-                mock.Mock(return_value=(0, "", ""))
-            ssh.from_node.return_value = ssh_mock
-            vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-            ixload_traffic_gen = IxLoadTrafficGen(NAME, vnfd)
-            self.assertIsNone(ixload_traffic_gen.resource_helper.data)
+    @mock.patch.object(ssh, 'SSH')
+    def test___init__(self, *args):
+        vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+        self.assertIsNone(ixload_traffic_gen.resource_helper.data)
 
-    def test_collect_kpi(self):
-        with mock.patch("yardstick.ssh.SSH") as ssh:
-            ssh_mock = mock.Mock(autospec=ssh.SSH)
-            ssh_mock.execute = \
-                mock.Mock(return_value=(0, "", ""))
-            ssh.from_node.return_value = ssh_mock
-            vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-            ixload_traffic_gen = IxLoadTrafficGen(NAME, vnfd)
-            ixload_traffic_gen.data = {}
-            restult = ixload_traffic_gen.collect_kpi()
-            self.assertEqual({}, restult)
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+                       return_value='mock_node')
+    @mock.patch.object(ssh, 'SSH')
+    def test_collect_kpi(self, *args):
+        vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+        ixload_traffic_gen.scenario_helper.scenario_cfg = {
+            'nodes': {ixload_traffic_gen.name: "mock"}
+        }
+        ixload_traffic_gen.data = {}
+        result = ixload_traffic_gen.collect_kpi()
 
-    def test_listen_traffic(self):
-        with mock.patch("yardstick.ssh.SSH") as ssh:
-            ssh_mock = mock.Mock(autospec=ssh.SSH)
-            ssh_mock.execute = \
-                mock.Mock(return_value=(0, "", ""))
-            ssh.from_node.return_value = ssh_mock
-            vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-            ixload_traffic_gen = IxLoadTrafficGen(NAME, vnfd)
-            self.assertIsNone(ixload_traffic_gen.listen_traffic({}))
+        expected = {
+            'physical_node': 'mock_node',
+            'collect_stats': {}}
+        self.assertEqual(expected, result)
+
+    @mock.patch.object(ssh, 'SSH')
+    def test_listen_traffic(self, *args):
+        vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+        self.assertIsNone(ixload_traffic_gen.listen_traffic({}))
 
     @mock.patch.object(utils, 'find_relative_file')
     @mock.patch.object(utils, 'makedirs')
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server')
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.shutil")
-    def test_instantiate(self, *args):
-        with mock.patch("yardstick.ssh.SSH") as ssh:
-            ssh_mock = mock.Mock(autospec=ssh.SSH)
-            ssh_mock.execute = \
-                mock.Mock(return_value=(0, "", ""))
-            ssh_mock.run = \
-                mock.Mock(return_value=(0, "", ""))
-            ssh.from_node.return_value = ssh_mock
-            vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-            ixload_traffic_gen = IxLoadTrafficGen(NAME, vnfd)
-            scenario_cfg = {'tc': "nsb_test_case",
-                            'ixia_profile': "ixload.cfg",
-                            'task_path': "/path/to/task"}
-            ixload_traffic_gen.RESULTS_MOUNT = "/tmp/result"
-            scenario_cfg.update({'options': {'packetsize': 64, 'traffic_type': 4,
-                                             'rfc2544': {'allowed_drop_rate': '0.8 - 1'},
-                                             'vnf__1': {'rules': 'acl_1rule.yaml',
-                                                        'vnf_config': {'lb_config': 'SW',
-                                                                       'lb_count': 1,
-                                                                       'worker_config':
-                                                                       '1C/1T',
-                                                                       'worker_threads': 1}}
-                                             }})
-            with mock.patch.object(six.moves.builtins, 'open',
-                                   create=True) as mock_open:
-                mock_open.return_value = mock.MagicMock()
-                ixload_traffic_gen.instantiate(scenario_cfg, {})
+    @mock.patch.object(ssh, 'SSH')
+    def test_instantiate(self, mock_shutil, *args):
+        vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+        scenario_cfg = {'tc': "nsb_test_case",
+                        'ixia_profile': "ixload.cfg",
+                        'task_path': "/path/to/task"}
+        ixload_traffic_gen.RESULTS_MOUNT = "/tmp/result"
+        mock_shutil.copy = mock.Mock()
+        scenario_cfg.update({'options': {'packetsize': 64, 'traffic_type': 4,
+                                         'rfc2544': {'allowed_drop_rate': '0.8 - 1'},
+                                         'vnf__1': {'rules': 'acl_1rule.yaml',
+                                                    'vnf_config': {'lb_config': 'SW',
+                                                                   'lb_count': 1,
+                                                                   'worker_config':
+                                                                   '1C/1T',
+                                                                   'worker_threads': 1}}
+                                         }})
+        scenario_cfg.update({
+            'nodes': {ixload_traffic_gen.name: "mock"}
+        })
+        with mock.patch.object(six.moves.builtins, 'open',
+                               create=True) as mock_open:
+            mock_open.return_value = mock.MagicMock()
+            ixload_traffic_gen.instantiate(scenario_cfg, {})
 
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.open")
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.min")
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.max")
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.len")
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.shutil")
+    @mock.patch.object(ssh, 'SSH')
     def test_run_traffic(self, *args):
         mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
-        with mock.patch("yardstick.ssh.SSH") as ssh:
-            ssh_mock = mock.Mock(autospec=ssh.SSH)
-            ssh_mock.execute = \
-                mock.Mock(return_value=(0, "", ""))
-            ssh_mock.run = \
-                mock.Mock(return_value=(0, "", ""))
-            ssh.from_node.return_value = ssh_mock
-            vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-            vnfd["mgmt-interface"].update({"tg-config": {}})
-            vnfd["mgmt-interface"]["tg-config"].update({"ixchassis":
-                                                        "1.1.1.1"})
-            vnfd["mgmt-interface"]["tg-config"].update({"py_bin_path":
-                                                        "/root"})
-            sut = IxLoadTrafficGen(NAME, vnfd)
-            sut.connection = mock.Mock()
-            sut.connection.run = mock.Mock()
-            sut._traffic_runner = mock.Mock(return_value=0)
-            result = sut.run_traffic(mock_traffic_profile)
-            self.assertIsNone(result)
+        vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        vnfd["mgmt-interface"].update({"tg-config": {}})
+        vnfd["mgmt-interface"]["tg-config"].update({"ixchassis":
+                                                    "1.1.1.1"})
+        vnfd["mgmt-interface"]["tg-config"].update({"py_bin_path":
+                                                    "/root"})
+        sut = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+        sut.connection = mock.Mock()
+        sut.connection.run = mock.Mock()
+        sut._traffic_runner = mock.Mock(return_value=0)
+        result = sut.run_traffic(mock_traffic_profile)
+        self.assertIsNone(result)
 
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.open")
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.min")
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.max")
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.len")
     @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.shutil")
+    @mock.patch.object(ssh, 'SSH')
     def test_run_traffic_csv(self, *args):
         mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
-        with mock.patch("yardstick.ssh.SSH") as ssh:
-            ssh_mock = mock.Mock(autospec=ssh.SSH)
-            ssh_mock.execute = \
-                mock.Mock(return_value=(0, "", ""))
-            ssh_mock.run = \
-                mock.Mock(return_value=(0, "", ""))
-            ssh.from_node.return_value = ssh_mock
-            vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-            vnfd["mgmt-interface"].update({"tg-config": {}})
-            vnfd["mgmt-interface"]["tg-config"].update({"ixchassis":
-                                                        "1.1.1.1"})
-            vnfd["mgmt-interface"]["tg-config"].update({"py_bin_path":
-                                                        "/root"})
-            sut = IxLoadTrafficGen(NAME, vnfd)
-            sut.connection = mock.Mock()
-            sut.connection.run = mock.Mock()
-            sut._traffic_runner = mock.Mock(return_value=0)
-            subprocess.call(["touch", "/tmp/1.csv"])
-            sut.rel_bin_path = mock.Mock(return_value="/tmp/*.csv")
-            result = sut.run_traffic(mock_traffic_profile)
-            self.assertIsNone(result)
+        vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        vnfd["mgmt-interface"].update({"tg-config": {}})
+        vnfd["mgmt-interface"]["tg-config"].update({"ixchassis":
+                                                    "1.1.1.1"})
+        vnfd["mgmt-interface"]["tg-config"].update({"py_bin_path":
+                                                    "/root"})
+        sut = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+        sut.connection = mock.Mock()
+        sut.connection.run = mock.Mock()
+        sut._traffic_runner = mock.Mock(return_value=0)
+        sut.rel_bin_path = mock.Mock(return_value="/tmp/*.csv")
+        result = sut.run_traffic(mock_traffic_profile)
+        self.assertIsNone(result)
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_ixload.call")
     @mock.patch.object(ssh, 'SSH')
     def test_terminate(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        ixload_traffic_gen = IxLoadTrafficGen(NAME, vnfd)
+        ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
         self.assertIsNone(ixload_traffic_gen.terminate())
 
-    @mock.patch("yardstick.ssh.SSH")
+    @mock.patch.object(ssh, 'SSH')
     def test_parse_csv_read(self, mock_ssh):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         kpi_data = {
@@ -273,15 +245,16 @@ class TestIxLoadTrafficGen(unittest.TestCase):
         mock_ssh_type.execute.return_value = 0, "", ""
         mock_ssh.from_node.return_value = mock_ssh_type
 
-        ixload_traffic_gen = IxLoadTrafficGen(NAME, vnfd)
+        ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
         result = ixload_traffic_gen.resource_helper.result
 
         ixload_traffic_gen.resource_helper.parse_csv_read(http_reader)
-        for key_left, key_right in IxLoadResourceHelper.KPI_LIST.items():
+        for key_left, key_right in (
+                tg_ixload.IxLoadResourceHelper.KPI_LIST.items()):
             self.assertEqual(result[key_left][-1], int(kpi_data[key_right]))
 
-    @mock.patch("yardstick.ssh.SSH")
-    def test_parse_csv_read_value_error(self, mock_ssh):
+    @mock.patch.object(ssh, 'SSH')
+    def test_parse_csv_read_value_error(self, mock_ssh, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         http_reader = [{
             'HTTP Total Throughput (Kbps)': 1,
@@ -295,14 +268,14 @@ class TestIxLoadTrafficGen(unittest.TestCase):
         mock_ssh_type.execute.return_value = 0, "", ""
         mock_ssh.from_node.return_value = mock_ssh_type
 
-        ixload_traffic_gen = IxLoadTrafficGen(NAME, vnfd)
+        ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
         init_value = ixload_traffic_gen.resource_helper.result
 
         ixload_traffic_gen.resource_helper.parse_csv_read(http_reader)
         self.assertDictEqual(ixload_traffic_gen.resource_helper.result, init_value)
 
     @mock.patch.object(ssh, 'SSH')
-    def test_parse_csv_read_error(self, mock_ssh):
+    def test_parse_csv_read_error(self, mock_ssh, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         http_reader = [{
             'HTTP Total Throughput (Kbps)': 1,
@@ -315,7 +288,7 @@ class TestIxLoadTrafficGen(unittest.TestCase):
         mock_ssh_type.execute.return_value = 0, "", ""
         mock_ssh.from_node.return_value = mock_ssh_type
 
-        ixload_traffic_gen = IxLoadTrafficGen(NAME, vnfd)
+        ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
 
         with self.assertRaises(KeyError):
             ixload_traffic_gen.resource_helper.parse_csv_read(http_reader)
index 14e0db7..d774bb9 100644 (file)
@@ -21,6 +21,7 @@ import unittest
 
 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
 from yardstick.tests import STL_MOCKS
+from yardstick.benchmark.contexts import base as ctx_base
 
 SSH_HELPER = "yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper"
 
@@ -253,14 +254,25 @@ class TestPingTrafficGen(unittest.TestCase):
         self.assertNotEqual(ext_ifs[0]['virtual-interface']['local_iface_name'], 'if_name_1')
         self.assertNotEqual(ext_ifs[1]['virtual-interface']['local_iface_name'], 'if_name_2')
 
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     @mock.patch("yardstick.ssh.SSH")
-    def test_collect_kpi(self, ssh):
+    def test_collect_kpi(self, ssh, *args):
         mock_ssh(ssh, exec_result=(0, "success", ""))
+
         ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
+        ping_traffic_gen.scenario_helper.scenario_cfg = {
+            'nodes': {ping_traffic_gen.name: "mock"}
+        }
         ping_traffic_gen._queue = Queue()
         ping_traffic_gen._queue.put({})
-        ping_traffic_gen.collect_kpi()
-        self.assertEqual(ping_traffic_gen._result, {})
+        expected = {
+            'physical_node': 'mock_node',
+            'collect_stats': {}
+        }
+        # NOTE: Why we check _result but not collect_kpi() return value
+        # self.assertEqual(ping_traffic_gen._result, {})
+        self.assertEqual(ping_traffic_gen.collect_kpi(), expected)
+
 
     @mock.patch(SSH_HELPER)
     def test_instantiate(self, ssh):
index f581ec8..3e2f598 100644 (file)
@@ -18,6 +18,7 @@ import mock
 
 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
 from yardstick.tests import STL_MOCKS
+from yardstick.benchmark.contexts import base as ctx_base
 
 
 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
@@ -324,15 +325,22 @@ class TestProxTrafficGen(unittest.TestCase):
         self.assertIsNone(prox_traffic_gen._tg_process)
         self.assertIsNone(prox_traffic_gen._traffic_process)
 
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     @mock.patch(SSH_HELPER)
     def test_collect_kpi(self, ssh, *args):
         mock_ssh(ssh)
-
         prox_traffic_gen = ProxTrafficGen(NAME, self.VNFD0)
+        prox_traffic_gen.scenario_helper.scenario_cfg = {
+            'nodes': {prox_traffic_gen.name: "mock"}
+        }
         prox_traffic_gen._vnf_wrapper.resource_helper.resource = mock.MagicMock(
             **{"self.check_if_system_agent_running.return_value": [False]})
         prox_traffic_gen._vnf_wrapper.vnf_execute = mock.Mock(return_value="")
-        self.assertEqual({}, prox_traffic_gen.collect_kpi())
+        expected = {
+            'collect_stats': {},
+            'physical_node': 'mock_node'
+        }
+        self.assertEqual(prox_traffic_gen.collect_kpi(), expected)
 
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.find_relative_file')
@@ -398,7 +406,8 @@ class TestProxTrafficGen(unittest.TestCase):
         sut.setup_helper.prox_config_dict = {}
         sut._connect_client = mock.Mock(autospec=STLClient)
         sut._connect_client.get_stats = mock.Mock(return_value="0")
-        sut._traffic_runner(mock_traffic_profile)
+        sut._setup_mq_producer = mock.Mock(return_value='mq_producer')
+        sut._traffic_runner(mock_traffic_profile, mock.ANY)
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket')
     @mock.patch(SSH_HELPER)
index 956c192..4ade157 100644 (file)
@@ -18,8 +18,10 @@ import mock
 import six
 import unittest
 
-from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_ixia
+from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
 from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_ixia
+from yardstick.benchmark.contexts import base as ctx_base
 
 
 TEST_FILE_YAML = 'nsb_test_case.yaml'
@@ -30,8 +32,7 @@ NAME = "tg__1"
 class TestIxiaResourceHelper(unittest.TestCase):
 
     def setUp(self):
-        self._mock_IxNextgen = mock.patch.object(tg_rfc2544_ixia,
-                                                 'IxNextgen')
+        self._mock_IxNextgen = mock.patch.object(ixnet_api, 'IxNextgen')
         self.mock_IxNextgen = self._mock_IxNextgen.start()
         self.addCleanup(self._stop_mocks)
 
@@ -48,12 +49,10 @@ class TestIxiaResourceHelper(unittest.TestCase):
 
     def test_stop_collect_with_client(self):
         mock_client = mock.Mock()
-
         ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock())
-
         ixia_resource_helper.client = mock_client
         ixia_resource_helper.stop_collect()
-        self.assertEqual(mock_client.ix_stop_traffic.call_count, 1)
+        self.assertEqual(1, ixia_resource_helper._terminated.value)
 
     def test_run_traffic(self):
         mock_tprofile = mock.Mock()
@@ -70,8 +69,7 @@ class TestIxiaResourceHelper(unittest.TestCase):
         self.assertEqual('fake_samples', ixia_rhelper._queue.get())
 
 
-@mock.patch(
-    "yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.IxNextgen")
+@mock.patch.object(tg_rfc2544_ixia, 'ixnet_api')
 class TestIXIATrafficGen(unittest.TestCase):
     VNFD = {'vnfd:vnfd-catalog':
             {'vnfd':
@@ -189,6 +187,7 @@ class TestIXIATrafficGen(unittest.TestCase):
             ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd)
             self.assertIsNone(ixnet_traffic_gen.listen_traffic({}))
 
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
     def test_instantiate(self, *args):
         with mock.patch("yardstick.ssh.SSH") as ssh:
             ssh_mock = mock.Mock(autospec=ssh.SSH)
@@ -215,6 +214,9 @@ class TestIXIATrafficGen(unittest.TestCase):
                                 'lb_count': 1,
                                 'worker_config': '1C/1T',
                                 'worker_threads': 1}}}})
+            scenario_cfg.update({
+                'nodes': {ixnet_traffic_gen.name: "mock"}
+            })
             ixnet_traffic_gen.topology = ""
             ixnet_traffic_gen.get_ixobj = mock.MagicMock()
             ixnet_traffic_gen._ixia_traffic_gen = mock.MagicMock()
@@ -223,17 +225,26 @@ class TestIXIATrafficGen(unittest.TestCase):
                 IOError,
                 ixnet_traffic_gen.instantiate(scenario_cfg, {}))
 
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     def test_collect_kpi(self, *args):
         with mock.patch("yardstick.ssh.SSH") as ssh:
             ssh_mock = mock.Mock(autospec=ssh.SSH)
             ssh_mock.execute = \
                 mock.Mock(return_value=(0, "", ""))
             ssh.from_node.return_value = ssh_mock
+
             vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
             ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd)
+            ixnet_traffic_gen.scenario_helper.scenario_cfg = {
+                'nodes': {ixnet_traffic_gen.name: "mock"}
+            }
             ixnet_traffic_gen.data = {}
             restult = ixnet_traffic_gen.collect_kpi()
-            self.assertEqual({}, restult)
+
+            expected = {'collect_stats': {},
+                        'physical_node': 'mock_node'}
+
+            self.assertEqual(expected, restult)
 
     def test_terminate(self, *args):
         with mock.patch("yardstick.ssh.SSH") as ssh:
@@ -368,7 +379,8 @@ class TestIXIATrafficGen(unittest.TestCase):
                     mock.mock_open(), create=True)
         @mock.patch('yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.LOG.exception')
         def _traffic_runner(*args):
-            result = sut._traffic_runner(mock_traffic_profile)
+            sut._setup_mq_producer = mock.Mock(return_value='mq_producer')
+            result = sut._traffic_runner(mock_traffic_profile, mock.ANY)
             self.assertIsNone(result)
 
         _traffic_runner()
index 8b1b8a3..4d3e4ff 100644 (file)
 # 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.
-#
 
-import unittest
 import mock
+import unittest
 
-from yardstick.tests import STL_MOCKS
-SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
-
-
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.tg_rfc2544_trex import TrexTrafficGenRFC, \
-        TrexRfcResourceHelper
-    from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_trex
-    from yardstick.network_services.traffic_profile.base import TrafficProfile
-    from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base \
-        import FileAbsPath, mock_ssh
-
-MODULE_PATH = FileAbsPath(__file__)
-get_file_abspath = MODULE_PATH.get_path
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_trex
+from yardstick.benchmark.contexts import base as ctx_base
 
 
 class TestTrexRfcResouceHelper(unittest.TestCase):
 
-    @mock.patch('yardstick.network_services.helpers.samplevnf_helper.MultiPortConfig')
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_trex.time")
-    @mock.patch(SSH_HELPER)
-    def test__run_traffic_once(self, ssh, *_):
-        mock_ssh(ssh)
+    def test__run_traffic_once(self):
+        mock_setup_helper = mock.Mock()
+        mock_traffic_profile = mock.Mock()
+        mock_traffic_profile.config.duration = 3
+        mock_traffic_profile.execute_traffic.return_value = ('fake_ports',
+                                                             'port_pg_id_map')
+        mock_traffic_profile.get_drop_percentage.return_value = 'percentage'
+        rfc_rh = tg_rfc2544_trex.TrexRfcResourceHelper(mock_setup_helper)
+        rfc_rh.TRANSIENT_PERIOD = 0
+        rfc_rh.rfc2544_helper = mock.Mock()
+
+        with mock.patch.object(rfc_rh, '_get_samples') as mock_get_samples:
+            rfc_rh._run_traffic_once(mock_traffic_profile)
 
-        mock_traffic_profile = mock.MagicMock(autospec=TrafficProfile,
-                                              **{'get_drop_percentage.return_value': {}})
-        sut = TrexRfcResourceHelper(mock.MagicMock(), mock.MagicMock())
-        sut.client = mock.MagicMock()
-        sut._run_traffic_once(mock_traffic_profile)
+        mock_traffic_profile.execute_traffic.assert_called_once_with(rfc_rh)
+        mock_traffic_profile.stop_traffic.assert_called_once_with(rfc_rh)
+        mock_traffic_profile.stop_traffic.assert_called_once()
+        mock_get_samples.assert_has_calls([
+            mock.call('fake_ports', port_pg_id='port_pg_id_map'),
+            mock.call('fake_ports', port_pg_id='port_pg_id_map')])
 
 
 class TestTrexTrafficGenRFC(unittest.TestCase):
@@ -219,33 +213,37 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
         'schema': 'yardstick:task:0.1',
     }
 
-    @mock.patch(SSH_HELPER)
-    def test___init__(self, ssh):
-        mock_ssh(ssh)
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        self.assertIsNotNone(trex_traffic_gen.resource_helper._terminated.value)
+    def setUp(self):
+        self._mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+        self.mock_ssh_helper = self._mock_ssh_helper.start()
+        self.addCleanup(self._stop_mocks)
 
-    @mock.patch(SSH_HELPER)
-    def test_collect_kpi(self, ssh):
-        mock_ssh(ssh)
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        self.assertEqual(trex_traffic_gen.collect_kpi(), {})
+    def _stop_mocks(self):
+        self._mock_ssh_helper.stop()
 
-    @mock.patch(SSH_HELPER)
-    def test_listen_traffic(self, ssh):
-        mock_ssh(ssh)
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        self.assertIsNone(trex_traffic_gen.listen_traffic({}))
+    def test___init__(self):
+        trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
+        self.assertIsNotNone(trex_traffic_gen.resource_helper._terminated.value)
 
-    @mock.patch(SSH_HELPER)
-    def test_instantiate(self, ssh):
-        mock_ssh(ssh)
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+    def test_collect_kpi(self, *args):
+        trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
+        trex_traffic_gen.scenario_helper.scenario_cfg = {
+            'nodes': {trex_traffic_gen.name: "mock"}
+        }
+        expected = {
+            'physical_node': 'mock_node',
+            'collect_stats': {},
+        }
+        self.assertEqual(trex_traffic_gen.collect_kpi(), expected)
 
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
+    def test_instantiate(self, *args):
+        mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
+        trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
         trex_traffic_gen._start_server = mock.Mock(return_value=0)
         trex_traffic_gen.resource_helper = mock.MagicMock()
         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
@@ -271,26 +269,24 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
             },
         }
         tg_rfc2544_trex.WAIT_TIME = 3
-        scenario_cfg.update({"nodes": ["tg_1", "vnf_1"]})
+        scenario_cfg.update({"nodes": {"tg_1": {}, "vnf1": {}}})
         self.assertIsNone(trex_traffic_gen.instantiate(scenario_cfg, {}))
 
-    @mock.patch(SSH_HELPER)
-    def test_instantiate_error(self, ssh):
-        mock_ssh(ssh, exec_result=(1, "", ""))
-
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
+    def test_instantiate_error(self, *args):
+        mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
+        trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
         trex_traffic_gen.resource_helper = mock.MagicMock()
         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
         scenario_cfg = {
             "tc": "tc_baremetal_rfc2544_ipv4_1flow_64B",
-            "nodes": [
-                "tg_1",
-                "vnf_1",
-            ],
+            "nodes": {
+                "tg_1": {},
+                "vnf1": {}
+            },
             "topology": 'nsb_test_case.yaml',
             'options': {
                 'packetsize': 64,
@@ -310,29 +306,3 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
             },
         }
         trex_traffic_gen.instantiate(scenario_cfg, {})
-
-    @mock.patch(SSH_HELPER)
-    def test__start_server(self, ssh):
-        mock_ssh(ssh)
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        trex_traffic_gen.resource_helper = mock.MagicMock()
-        self.assertIsNone(trex_traffic_gen._start_server())
-
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_trex.time")
-    @mock.patch(SSH_HELPER)
-    def test__generate_trex_cfg(self, ssh, _):
-        mock_ssh(ssh)
-
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        trex_traffic_gen.ssh_helper = mock.MagicMock()
-        trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
-        self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
-
-    def test_terminate(self):
-        with mock.patch(SSH_HELPER) as ssh:
-            ssh_mock = mock.Mock(autospec=ssh.SSH)
-            ssh_mock.execute = mock.Mock(return_value=(0, "", ""))
-            ssh.from_node.return_value = ssh_mock
-            trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-            trex_traffic_gen.resource_helper = mock.MagicMock()
-            self.assertIsNone(trex_traffic_gen.terminate())
index aae3d46..700e910 100644 (file)
 # 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.
-#
 
 import copy
 
 import mock
 import unittest
 
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
-from yardstick.tests import STL_MOCKS
-
-
-SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
-NAME = 'vnf_1'
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import rfc2544
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_trex
+from yardstick.benchmark.contexts import base as ctx_base
 
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
 
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.tg_trex import \
-        TrexTrafficGen, TrexResourceHelper
-    from yardstick.network_services.traffic_profile.base import TrafficProfile
+NAME = 'vnf__1'
 
 
 class TestTrexTrafficGen(unittest.TestCase):
+
     VNFD = {'vnfd:vnfd-catalog':
             {'vnfd':
              [{'short-name': 'VpeVnf',
@@ -168,7 +161,7 @@ class TestTrexTrafficGen(unittest.TestCase):
                 "interfaces": {
                     "xe0": {
                         "local_iface_name": "ens786f0",
-                        "vld_id": TrafficProfile.UPLINK,
+                        "vld_id": tp_base.TrafficProfile.UPLINK,
                         "netmask": "255.255.255.0",
                         "vpci": "0000:05:00.0",
                         "local_ip": "152.16.100.19",
@@ -180,7 +173,7 @@ class TestTrexTrafficGen(unittest.TestCase):
                     },
                     "xe1": {
                         "local_iface_name": "ens786f1",
-                        "vld_id": TrafficProfile.DOWNLINK,
+                        "vld_id": tp_base.TrafficProfile.DOWNLINK,
                         "netmask": "255.255.255.0",
                         "vpci": "0000:05:00.1",
                         "local_ip": "152.16.40.19",
@@ -236,7 +229,7 @@ class TestTrexTrafficGen(unittest.TestCase):
                 "interfaces": {
                     "xe0": {
                         "local_iface_name": "ens513f0",
-                        "vld_id": TrafficProfile.DOWNLINK,
+                        "vld_id": tp_base.TrafficProfile.DOWNLINK,
                         "netmask": "255.255.255.0",
                         "vpci": "0000:02:00.0",
                         "local_ip": "152.16.40.20",
@@ -270,7 +263,7 @@ class TestTrexTrafficGen(unittest.TestCase):
                 "interfaces": {
                     "xe0": {
                         "local_iface_name": "ens785f0",
-                        "vld_id": TrafficProfile.UPLINK,
+                        "vld_id": tp_base.TrafficProfile.UPLINK,
                         "netmask": "255.255.255.0",
                         "vpci": "0000:05:00.0",
                         "local_ip": "152.16.100.20",
@@ -297,36 +290,44 @@ class TestTrexTrafficGen(unittest.TestCase):
         }
     }
 
-    @mock.patch(SSH_HELPER)
-    def test___init__(self, ssh):
-        mock_ssh(ssh)
+    def setUp(self):
+        self._mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+        self.mock_ssh_helper = self._mock_ssh_helper.start()
+        self.addCleanup(self._stop_mocks)
+
+    def _stop_mocks(self):
+        self._mock_ssh_helper.stop()
+
+    def test___init__(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
-        self.assertIsInstance(
-            trex_traffic_gen.resource_helper, TrexResourceHelper)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+        self.assertIsInstance(trex_traffic_gen.resource_helper,
+                              tg_trex.TrexResourceHelper)
 
-    @mock.patch(SSH_HELPER)
-    def test_collect_kpi(self, ssh):
-        mock_ssh(ssh)
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+    def test_collect_kpi(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen.scenario_helper.scenario_cfg = {
+            'nodes': {trex_traffic_gen.name: "mock"}
+        }
         trex_traffic_gen.resource_helper._queue.put({})
         result = trex_traffic_gen.collect_kpi()
-        self.assertEqual({}, result)
+        expected = {
+            'physical_node': 'mock_node',
+            'collect_stats': {}
+        }
+        self.assertEqual(expected, result)
 
-    @mock.patch(SSH_HELPER)
-    def test_listen_traffic(self, ssh):
-        mock_ssh(ssh)
+    def test_listen_traffic(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         self.assertIsNone(trex_traffic_gen.listen_traffic({}))
 
-    @mock.patch(SSH_HELPER)
-    def test_instantiate(self, ssh):
-        mock_ssh(ssh)
-
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
+    def test_instantiate(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen._start_server = mock.Mock(return_value=0)
         trex_traffic_gen._tg_process = mock.MagicMock()
         trex_traffic_gen._tg_process.start = mock.Mock()
@@ -335,16 +336,13 @@ class TestTrexTrafficGen(unittest.TestCase):
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
+        self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG,
+                                                       self.CONTEXT_CFG))
 
-        self.assertIsNone(trex_traffic_gen.instantiate(
-            self.SCENARIO_CFG, self.CONTEXT_CFG))
-
-    @mock.patch(SSH_HELPER)
-    def test_instantiate_error(self, ssh):
-        mock_ssh(ssh, exec_result=(1, "", ""))
-
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
+    def test_instantiate_error(self, *args):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen._start_server = mock.Mock(return_value=0)
         trex_traffic_gen._tg_process = mock.MagicMock()
         trex_traffic_gen._tg_process.start = mock.Mock()
@@ -352,62 +350,54 @@ class TestTrexTrafficGen(unittest.TestCase):
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
-        self.assertIsNone(trex_traffic_gen.instantiate(
-            self.SCENARIO_CFG, self.CONTEXT_CFG))
+        self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG,
+                                                       self.CONTEXT_CFG))
 
-    @mock.patch(SSH_HELPER)
-    def test__start_server(self, ssh):
-        mock_ssh(ssh)
+    def test__start_server(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.scenario_helper.scenario_cfg = {}
         self.assertIsNone(trex_traffic_gen._start_server())
 
-    @mock.patch(SSH_HELPER)
-    def test__start_server_multiple_queues(self, ssh):
-        mock_ssh(ssh)
+    def test__start_server_multiple_queues(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.scenario_helper.scenario_cfg = {
             "options": {NAME: {"queues_per_port": 2}}}
         self.assertIsNone(trex_traffic_gen._start_server())
 
-    @mock.patch(SSH_HELPER)
-    def test__traffic_runner(self, ssh):
-        mock_ssh(ssh)
-
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+    def test__traffic_runner(self):
+        mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.execute_traffic.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        self.sut = TrexTrafficGen(NAME, vnfd)
+        self.sut = tg_trex.TrexTrafficGen(NAME, vnfd)
         self.sut.ssh_helper = mock.Mock()
         self.sut.ssh_helper.run = mock.Mock()
-        self.sut._connect_client = mock.Mock(autospec=STLClient)
+        self.sut._connect_client = mock.Mock()
         self.sut._connect_client.get_stats = mock.Mock(return_value="0")
         self.sut.resource_helper.RUN_DURATION = 0
         self.sut.resource_helper.QUEUE_WAIT_TIME = 0
-        # must generate cfg before we can run traffic so Trex port mapping is created
+        # must generate cfg before we can run traffic so Trex port mapping is
+        # created
         self.sut.resource_helper.generate_cfg()
-        self.sut._traffic_runner(mock_traffic_profile)
+        self.sut._setup_mq_producer = mock.Mock()
+        with mock.patch.object(self.sut.resource_helper, 'run_traffic'):
+            self.sut._traffic_runner(mock_traffic_profile, mock.ANY)
 
-    @mock.patch(SSH_HELPER)
-    def test__generate_trex_cfg(self, ssh):
-        mock_ssh(ssh)
+    def test__generate_trex_cfg(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
 
-    @mock.patch(SSH_HELPER)
-    def test_build_ports_reversed_pci_ordering(self, ssh):
-        mock_ssh(ssh)
+    def test_build_ports_reversed_pci_ordering(self):
         vnfd = copy.deepcopy(self.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
         vnfd['vdu'][0]['external-interface'] = [
             {'virtual-interface':
@@ -442,48 +432,85 @@ class TestTrexTrafficGen(unittest.TestCase):
               'local_mac': '00:00:00:00:00:01'},
              'vnfd-connection-point-ref': 'xe1',
              'name': 'xe1'}]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.generate_cfg()
         trex_traffic_gen.resource_helper._build_ports()
-        self.assertEqual(
-            sorted(trex_traffic_gen.resource_helper.all_ports), [0, 1])
+        self.assertEqual(sorted(trex_traffic_gen.resource_helper.all_ports),
+                         [0, 1])
         # there is a gap in ordering
-        self.assertEqual(dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map),
-                         {0: 0, 2: 1})
-
-    @mock.patch(SSH_HELPER)
-    def test_run_traffic(self, ssh):
-        mock_ssh(ssh)
+        self.assertEqual(
+            {0: 0, 2: 1},
+            dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map))
 
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+    def test_run_traffic(self):
+        mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        self.sut = TrexTrafficGen(NAME, vnfd)
+        self.sut = tg_trex.TrexTrafficGen(NAME, vnfd)
         self.sut.ssh_helper = mock.Mock()
         self.sut.ssh_helper.run = mock.Mock()
         self.sut._traffic_runner = mock.Mock(return_value=0)
         self.sut.resource_helper.client_started.value = 1
-        result = self.sut.run_traffic(mock_traffic_profile)
+        self.sut.run_traffic(mock_traffic_profile)
         self.sut._traffic_process.terminate()
-        self.assertIsNotNone(result)
 
-    @mock.patch(SSH_HELPER)
-    def test_terminate(self, ssh):
-        mock_ssh(ssh)
+    def test_terminate(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         self.assertIsNone(trex_traffic_gen.terminate())
 
-    @mock.patch(SSH_HELPER)
-    def test__connect_client(self, ssh):
-        mock_ssh(ssh)
+    def test__connect_client(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
-        client = mock.Mock(autospec=STLClient)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+        client = mock.Mock()
         client.connect = mock.Mock(return_value=0)
         self.assertIsNotNone(trex_traffic_gen.resource_helper._connect(client))
+
+
+class TrexResourceHelperTestCase(unittest.TestCase):
+
+    def test__get_samples(self):
+        mock_setup_helper = mock.Mock()
+        trex_rh = tg_trex.TrexResourceHelper(mock_setup_helper)
+        trex_rh.vnfd_helper.interfaces = [
+            {'name': 'interface1'},
+            {'name': 'interface2'}]
+        stats = {
+            10: {'rx_pps': 5, 'ipackets': 200},
+            20: {'rx_pps': 10, 'ipackets': 300},
+            'latency': {1: {'latency': 'latency_port_10_pg_id_1'},
+                        2: {'latency': 'latency_port_10_pg_id_2'},
+                        3: {'latency': 'latency_port_20_pg_id_3'},
+                        4: {'latency': 'latency_port_20_pg_id_4'}}
+        }
+        port_pg_id = rfc2544.PortPgIDMap()
+        port_pg_id.add_port(10)
+        port_pg_id.increase_pg_id()
+        port_pg_id.increase_pg_id()
+        port_pg_id.add_port(20)
+        port_pg_id.increase_pg_id()
+        port_pg_id.increase_pg_id()
+
+        with mock.patch.object(trex_rh, 'get_stats') as mock_get_stats, \
+                mock.patch.object(trex_rh.vnfd_helper, 'port_num') as \
+                mock_port_num:
+            mock_get_stats.return_value = stats
+            mock_port_num.side_effect = [10, 20]
+            output = trex_rh._get_samples([10, 20], port_pg_id=port_pg_id)
+
+        interface = output['interface1']
+        self.assertEqual(5.0, interface['rx_throughput_fps'])
+        self.assertEqual(200, interface['in_packets'])
+        self.assertEqual('latency_port_10_pg_id_1', interface['latency'][1])
+        self.assertEqual('latency_port_10_pg_id_2', interface['latency'][2])
+
+        interface = output['interface2']
+        self.assertEqual(10.0, interface['rx_throughput_fps'])
+        self.assertEqual(300, interface['in_packets'])
+        self.assertEqual('latency_port_20_pg_id_3', interface['latency'][3])
+        self.assertEqual('latency_port_20_pg_id_4', interface['latency'][4])
index 05a0ead..1c4ced3 100644 (file)
@@ -19,6 +19,7 @@ import os
 
 from yardstick.tests import STL_MOCKS
 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+from yardstick.benchmark.contexts import base as ctx_base
 
 
 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
@@ -330,6 +331,7 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
         self.assertIsNone(udp_replay_approx_vnf._vnf_process)
 
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     @mock.patch(SSH_HELPER)
     def test_collect_kpi(self, ssh, *args):
         mock_ssh(ssh)
@@ -341,14 +343,21 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
             "0\t\t7374156\t\t7374136\t\t\t0\t\t\t0\r\n" \
             "1\t\t7374316\t\t7374315\t\t\t0\t\t\t0\r\n\r\nReplay>\r\r\nReplay>"
         udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, vnfd)
+        udp_replay_approx_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {udp_replay_approx_vnf.name: "mock"}
+        }
         udp_replay_approx_vnf.q_in = mock.MagicMock()
         udp_replay_approx_vnf.q_out = mock.MagicMock()
         udp_replay_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
         udp_replay_approx_vnf.all_ports = ["xe0", "xe1"]
         udp_replay_approx_vnf.get_stats = mock.Mock(return_value=get_stats_ret_val)
-
-        result = {'collect_stats': {}, 'packets_dropped': 0,
-                  'packets_fwd': 14748451, 'packets_in': 14748472}
+        result = {
+            'physical_node': 'mock_node',
+            'collect_stats': {},
+            'packets_dropped': 0,
+            'packets_fwd': 14748451,
+            'packets_in': 14748472
+        }
         self.assertEqual(result, udp_replay_approx_vnf.collect_kpi())
 
     @mock.patch(SSH_HELPER)
@@ -372,14 +381,18 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
         file_path = os.path.join(curr_path, filename)
         return file_path
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server')
     @mock.patch(SSH_HELPER)
-    def test__build_config(self, ssh, mock_context, *args):
+    def test__build_config(self, ssh, mock_get_ctx, *args):
         mock_ssh(ssh)
 
+        nfvi_context = mock.Mock()
+        nfvi_context.attrs = {'nfvi_type': 'baremetal'}
+        mock_get_ctx.return_value = nfvi_context
+
         udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
         udp_replay_approx_vnf.queue_wrapper = mock.MagicMock()
-        udp_replay_approx_vnf.nfvi_context = mock_context
+        udp_replay_approx_vnf.nfvi_context = mock_get_ctx
         udp_replay_approx_vnf.nfvi_context.attrs = {'nfvi_type': 'baremetal'}
         udp_replay_approx_vnf.setup_helper.bound_pci = []
         udp_replay_approx_vnf.ssh_helper.provision_tool = mock.MagicMock(return_value="tool_path")
@@ -393,13 +406,16 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
         self.assertEqual(cmd_line, expected)
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.udp_replay.open')
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server')
     @mock.patch(SSH_HELPER)
-    def test__build_pipeline_kwargs(self, ssh, mock_context, *args):
+    def test__build_pipeline_kwargs(self, ssh, mock_get_ctx, *args):
         mock_ssh(ssh)
+
+        nfvi_context = mock.Mock()
+        nfvi_context.attrs = {'nfvi_type': "baremetal"}
+        mock_get_ctx.return_value = nfvi_context
+
         udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
-        udp_replay_approx_vnf.nfvi_context = mock_context
-        udp_replay_approx_vnf.nfvi_context.attrs = {'nfvi_type': 'baremetal'}
         udp_replay_approx_vnf.setup_helper.bound_pci = ['0000:00:0.1', '0000:00:0.3']
         udp_replay_approx_vnf.all_ports = ["xe0", "xe1"]
         udp_replay_approx_vnf.ssh_helper.provision_tool = mock.MagicMock(return_value="tool_path")
@@ -430,7 +446,7 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
 
         udp_replay_approx_vnf.ssh_helper.run.assert_called_once()
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server')
     @mock.patch(SSH_HELPER)
     def test_instantiate(self, ssh, *args):
         mock_ssh(ssh)
@@ -449,7 +465,7 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
 
         self.assertEqual(udp_replay_approx_vnf.wait_for_instantiate(), 0)
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server')
     @mock.patch('yardstick.ssh.SSH')
     @mock.patch(SSH_HELPER)
     def test_instantiate_panic(self, *args):
index ffb5cd6..b67a3cd 100644 (file)
@@ -21,7 +21,7 @@ from yardstick.tests import STL_MOCKS
 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
 
 from yardstick.common import utils
-
+from yardstick.benchmark.contexts import base as ctx_base
 
 STLClient = mock.MagicMock()
 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
@@ -259,12 +259,15 @@ pipeline>
 """  # noqa
 
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
     @mock.patch(SSH_HELPER)
     def test_collect_kpi(self, ssh, *args):
         mock_ssh(ssh)
-
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         vfw_approx_vnf = FWApproxVnf(name, vnfd)
+        vfw_approx_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {vfw_approx_vnf.name: "mock"}
+        }
         vfw_approx_vnf.q_in = mock.MagicMock()
         vfw_approx_vnf.q_out = mock.MagicMock()
         vfw_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
@@ -273,6 +276,7 @@ pipeline>
             **{'collect_kpi.return_value': {"core": {}}})
         vfw_approx_vnf.vnf_execute = mock.Mock(return_value=self.STATS)
         result = {
+            'physical_node': 'mock_node',
             'packets_dropped': 0,
             'packets_fwd': 6007180,
             'packets_in': 6007180,
@@ -334,8 +338,7 @@ pipeline>
         vfw_approx_vnf.ssh_helper.run.assert_called_once()
 
     @mock.patch.object(utils, 'find_relative_file')
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.vfw_vnf.YangModel")
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
+    @mock.patch.object(ctx_base.Context, 'get_context_from_server')
     @mock.patch(SSH_HELPER)
     def test_instantiate(self, ssh, *args):
         mock_ssh(ssh)
@@ -363,12 +366,15 @@ class TestFWApproxSetupEnvHelper(unittest.TestCase):
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+        scenario_helper.options = {}
         scenario_helper.all_options = {}
 
         vfw_approx_setup_helper = FWApproxSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        vfw_approx_setup_helper.get_flows_config = mock.Mock()
 
         vfw_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
         vfw_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
         vfw_approx_setup_helper.vnfd_helper.port_nums = mock.Mock(return_value=[0, 1])
         expected = 'sudo tool_path -p 0x3 -f /tmp/vfw_config -s /tmp/vfw_script  --hwlb 3'
         self.assertEqual(vfw_approx_setup_helper.build_config(), expected)
+        vfw_approx_setup_helper.get_flows_config.assert_called_once()
index 4fd51f0..c1664f2 100644 (file)
 # 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.
-#
 
 from multiprocessing import Process, Queue
-import os
 import time
 
 import mock
 from six.moves import configparser
 import unittest
 
-from yardstick.tests import STL_MOCKS
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import FileAbsPath
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
-from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper
-from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
-
-
-SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
-
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.vpe_vnf import ConfigCreate
-    from yardstick.network_services.nfvi.resource import ResourceProfile
-    from yardstick.network_services.vnf_generic.vnf.vpe_vnf import \
-        VpeApproxVnf, VpeApproxSetupEnvHelper
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.nfvi.resource import ResourceProfile
+from yardstick.network_services.vnf_generic.vnf import base as vnf_base
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import vpe_vnf
+from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base
 
 
 TEST_FILE_YAML = 'nsb_test_case.yaml'
@@ -47,7 +33,7 @@ NAME = 'vnf_1'
 
 PING_OUTPUT_1 = "Pkts in: 101\r\n\tPkts dropped by AH: 100\r\n\tPkts dropped by other: 100"
 
-MODULE_PATH = FileAbsPath(__file__)
+MODULE_PATH = test_base.FileAbsPath(__file__)
 get_file_abspath = MODULE_PATH.get_path
 
 
@@ -155,20 +141,20 @@ class TestConfigCreate(unittest.TestCase):
     }
 
     def test___init__(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        config_create = ConfigCreate(vnfd_helper, 2)
+        vnfd_helper = vnf_base.VnfdHelper(self.VNFD_0)
+        config_create = vpe_vnf.ConfigCreate(vnfd_helper, 2)
         self.assertEqual(config_create.uplink_ports, ['xe0'])
         self.assertEqual(config_create.downlink_ports, ['xe1'])
         self.assertEqual(config_create.socket, 2)
 
     def test_dpdk_port_to_link_id(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        config_create = ConfigCreate(vnfd_helper, 2)
+        vnfd_helper = vnf_base.VnfdHelper(self.VNFD_0)
+        config_create = vpe_vnf.ConfigCreate(vnfd_helper, 2)
         self.assertEqual(config_create.dpdk_port_to_link_id_map, {'xe0': 0, 'xe1': 1})
 
     def test_vpe_initialize(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        config_create = ConfigCreate(vnfd_helper, 2)
+        vnfd_helper = vnf_base.VnfdHelper(self.VNFD_0)
+        config_create = vpe_vnf.ConfigCreate(vnfd_helper, 2)
         config = configparser.ConfigParser()
         config_create.vpe_initialize(config)
         self.assertEqual(config.get('EAL', 'log_level'), '0')
@@ -178,16 +164,16 @@ class TestConfigCreate(unittest.TestCase):
         self.assertEqual(config.get('MEMPOOL1', 'pool_size'), '2M')
 
     def test_vpe_rxq(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        config_create = ConfigCreate(vnfd_helper, 2)
+        vnfd_helper = vnf_base.VnfdHelper(self.VNFD_0)
+        config_create = vpe_vnf.ConfigCreate(vnfd_helper, 2)
         config = configparser.ConfigParser()
         config_create.downlink_ports = ['xe0']
         config_create.vpe_rxq(config)
         self.assertEqual(config.get('RXQ0.0', 'mempool'), 'MEMPOOL1')
 
     def test_get_sink_swq(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        config_create = ConfigCreate(vnfd_helper, 2)
+        vnfd_helper = vnf_base.VnfdHelper(self.VNFD_0)
+        config_create = vpe_vnf.ConfigCreate(vnfd_helper, 2)
         config = configparser.ConfigParser()
         config.add_section('PIPELINE0')
         config.set('PIPELINE0', 'key1', 'value1')
@@ -204,8 +190,8 @@ class TestConfigCreate(unittest.TestCase):
         self.assertEqual(config_create.get_sink_swq(config, 'PIPELINE0', 'key5', 5), 'SWQ0 SINK1')
 
     def test_generate_vpe_script(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        vpe_config_vnf = ConfigCreate(vnfd_helper, 2)
+        vnfd_helper = vnf_base.VnfdHelper(self.VNFD_0)
+        vpe_config_vnf = vpe_vnf.ConfigCreate(vnfd_helper, 2)
         intf = [
             {
                 "name": 'xe1',
@@ -229,15 +215,34 @@ class TestConfigCreate(unittest.TestCase):
         self.assertNotEqual(result, '')
 
     def test_create_vpe_config(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        config_create = ConfigCreate(vnfd_helper, 23)
-        config_create.downlink_ports = ['xe1']
+        vnfd_helper = vnf_base.VnfdHelper(self.VNFD_0)
+        config_create = vpe_vnf.ConfigCreate(vnfd_helper, 23)
         config_create.uplink_ports = ['xe1']
-        curr_path = os.path.dirname(os.path.abspath(__file__))
-        vpe_cfg = "samples/vnf_samples/nsut/vpe/vpe_config"
-        vnf_cfg = os.path.join(curr_path, "../../../../..", vpe_cfg)
-        config_create.create_vpe_config(vnf_cfg)
-        os.system("git checkout -- %s" % vnf_cfg)
+        with mock.patch.object(config_create, 'vpe_upstream') as mock_up, \
+                mock.patch.object(config_create, 'vpe_downstream') as \
+                mock_down, \
+                mock.patch.object(config_create, 'vpe_tmq') as mock_tmq, \
+                mock.patch.object(config_create, 'vpe_initialize') as \
+                mock_ini, \
+                mock.patch.object(config_create, 'vpe_rxq') as mock_rxq:
+            mock_ini_obj = mock.Mock()
+            mock_rxq_obj = mock.Mock()
+            mock_up_obj = mock.Mock()
+            mock_down_obj = mock.Mock()
+            mock_tmq_obj = mock.Mock()
+            mock_ini.return_value = mock_ini_obj
+            mock_rxq.return_value = mock_rxq_obj
+            mock_up.return_value = mock_up_obj
+            mock_down.return_value = mock_down_obj
+            mock_tmq.return_value = mock_tmq_obj
+            config_create.create_vpe_config('fake_config_file')
+
+        mock_rxq.assert_called_once_with(mock_ini_obj)
+        mock_up.assert_called_once_with('fake_config_file', 0)
+        mock_down.assert_called_once_with('fake_config_file', 0)
+        mock_tmq.assert_called_once_with(mock_down_obj, 0)
+        mock_up_obj.write.assert_called_once()
+        mock_tmq_obj.write.assert_called_once()
 
 
 class TestVpeApproxVnf(unittest.TestCase):
@@ -409,7 +414,7 @@ class TestVpeApproxVnf(unittest.TestCase):
                 'interfaces': {
                     'xe0': {
                         'local_iface_name': 'ens513f0',
-                        'vld_id': VpeApproxVnf.DOWNLINK,
+                        'vld_id': vpe_vnf.VpeApproxVnf.DOWNLINK,
                         'netmask': '255.255.255.0',
                         'local_ip': '152.16.40.20',
                         'dst_mac': '00:00:00:00:00:01',
@@ -443,7 +448,7 @@ class TestVpeApproxVnf(unittest.TestCase):
                 'interfaces': {
                     'xe0': {
                         'local_iface_name': 'ens785f0',
-                        'vld_id': VpeApproxVnf.UPLINK,
+                        'vld_id': vpe_vnf.VpeApproxVnf.UPLINK,
                         'netmask': '255.255.255.0',
                         'local_ip': '152.16.100.20',
                         'dst_mac': '00:00:00:00:00:02',
@@ -474,7 +479,7 @@ class TestVpeApproxVnf(unittest.TestCase):
                 'interfaces': {
                     'xe0': {
                         'local_iface_name': 'ens786f0',
-                        'vld_id': VpeApproxVnf.UPLINK,
+                        'vld_id': vpe_vnf.VpeApproxVnf.UPLINK,
                         'netmask': '255.255.255.0',
                         'local_ip': '152.16.100.19',
                         'dst_mac': '00:00:00:00:00:04',
@@ -486,7 +491,7 @@ class TestVpeApproxVnf(unittest.TestCase):
                     },
                     'xe1': {
                         'local_iface_name': 'ens786f1',
-                        'vld_id': VpeApproxVnf.DOWNLINK,
+                        'vld_id': vpe_vnf.VpeApproxVnf.DOWNLINK,
                         'netmask': '255.255.255.0',
                         'local_ip': '152.16.40.19',
                         'dst_mac': '00:00:00:00:00:03',
@@ -536,28 +541,39 @@ class TestVpeApproxVnf(unittest.TestCase):
     }
 
     def setUp(self):
-        self.mock_sleep = mock.patch.object(time, 'sleep').start()
+        self._mock_time_sleep = mock.patch.object(time, 'sleep')
+        self.mock_time_sleep = self._mock_time_sleep.start()
+        self.addCleanup(self._stop_mocks)
+
+    def _stop_mocks(self):
+        self._mock_time_sleep.stop()
 
     def test___init__(self):
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
         self.assertIsNone(vpe_approx_vnf._vnf_process)
 
-    @mock.patch(SSH_HELPER)
-    def test_collect_kpi_sa_not_running(self, ssh):
-        mock_ssh(ssh)
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+                       return_value='mock_node')
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
+    def test_collect_kpi_sa_not_running(self, ssh, *args):
+        test_base.mock_ssh(ssh)
 
         resource = mock.Mock(autospec=ResourceProfile)
         resource.check_if_system_agent_running.return_value = 1, ''
         resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
         resource.check_if_system_agent_running.return_value = (1, None)
 
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {vpe_approx_vnf.name: "mock"}
+        }
         vpe_approx_vnf.q_in = mock.MagicMock()
         vpe_approx_vnf.q_out = mock.MagicMock()
         vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
         vpe_approx_vnf.resource_helper.resource = resource
 
         expected = {
+            'physical_node': 'mock_node',
             'pkt_in_down_stream': 0,
             'pkt_in_up_stream': 0,
             'pkt_drop_down_stream': 0,
@@ -566,21 +582,27 @@ class TestVpeApproxVnf(unittest.TestCase):
         }
         self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
 
-    @mock.patch(SSH_HELPER)
-    def test_collect_kpi_sa_running(self, ssh):
-        mock_ssh(ssh)
+    @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+                       return_value='mock_node')
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
+    def test_collect_kpi_sa_running(self, ssh, *args):
+        test_base.mock_ssh(ssh)
 
         resource = mock.Mock(autospec=ResourceProfile)
         resource.check_if_system_agent_running.return_value = 0, '1234'
         resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
 
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf.scenario_helper.scenario_cfg = {
+            'nodes': {vpe_approx_vnf.name: "mock"}
+        }
         vpe_approx_vnf.q_in = mock.MagicMock()
         vpe_approx_vnf.q_out = mock.MagicMock()
         vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
         vpe_approx_vnf.resource_helper.resource = resource
 
         expected = {
+            'physical_node': 'mock_node',
             'pkt_in_down_stream': 0,
             'pkt_in_up_stream': 0,
             'pkt_drop_down_stream': 0,
@@ -589,20 +611,20 @@ class TestVpeApproxVnf(unittest.TestCase):
         }
         self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
 
-    @mock.patch(SSH_HELPER)
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
     def test_vnf_execute(self, ssh):
-        mock_ssh(ssh)
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        test_base.mock_ssh(ssh)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
         vpe_approx_vnf.q_in = mock.MagicMock()
         vpe_approx_vnf.q_out = mock.MagicMock()
         vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
         self.assertEqual(vpe_approx_vnf.vnf_execute("quit", 0), '')
 
-    @mock.patch(SSH_HELPER)
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
     def test_run_vpe(self, ssh):
-        mock_ssh(ssh)
+        test_base.mock_ssh(ssh)
 
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
         vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
         vpe_approx_vnf.vnf_cfg = {
             'lb_config': 'SW',
@@ -629,14 +651,13 @@ class TestVpeApproxVnf(unittest.TestCase):
         self.assertIsNone(vpe_approx_vnf._run())
 
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig")
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
     @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.ConfigCreate")
     @mock.patch("six.moves.builtins.open")
-    @mock.patch(SSH_HELPER)
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
     def test_build_config(self, ssh, *args):
-        mock_ssh(ssh)
-        vpe_approx_vnf = VpeApproxSetupEnvHelper(mock.MagicMock(),
-                                                 mock.MagicMock(), mock.MagicMock())
+        test_base.mock_ssh(ssh)
+        vpe_approx_vnf = vpe_vnf.VpeApproxSetupEnvHelper(
+            mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
         vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
         vpe_approx_vnf.generate_port_pairs = mock.Mock()
         vpe_approx_vnf.vnf_cfg = {
@@ -672,9 +693,9 @@ class TestVpeApproxVnf(unittest.TestCase):
         expected = 'sudo tool_path -p 0x3 -f /tmp/vpe_config -s /tmp/vpe_script  --hwlb 3'
         self.assertEqual(vpe_approx_vnf.build_config(), expected)
 
-    @mock.patch(SSH_HELPER)
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
     def test_wait_for_instantiate(self, ssh):
-        mock_ssh(ssh)
+        test_base.mock_ssh(ssh)
 
         mock_process = mock.Mock(autospec=Process)
         mock_process.is_alive.return_value = True
@@ -686,18 +707,19 @@ class TestVpeApproxVnf(unittest.TestCase):
 
         mock_resource = mock.MagicMock()
 
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
         vpe_approx_vnf._vnf_process = mock_process
         vpe_approx_vnf.q_out = mock_q_out
-        vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
+        vpe_approx_vnf.queue_wrapper = mock.Mock(
+            autospec=vnf_base.QueueFileWrapper)
         vpe_approx_vnf.resource_helper.resource = mock_resource
 
         vpe_approx_vnf.q_out.put("pipeline>")
         self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
 
-    @mock.patch(SSH_HELPER)
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
     def test_wait_for_instantiate_fragmented(self, ssh):
-        mock_ssh(ssh)
+        test_base.mock_ssh(ssh)
 
         mock_process = mock.Mock(autospec=Process)
         mock_process.is_alive.return_value = True
@@ -710,17 +732,18 @@ class TestVpeApproxVnf(unittest.TestCase):
 
         mock_resource = mock.MagicMock()
 
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
         vpe_approx_vnf._vnf_process = mock_process
         vpe_approx_vnf.q_out = mock_q_out
-        vpe_approx_vnf.queue_wrapper = mock.Mock(autospec=QueueFileWrapper)
+        vpe_approx_vnf.queue_wrapper = mock.Mock(
+            autospec=vnf_base.QueueFileWrapper)
         vpe_approx_vnf.resource_helper.resource = mock_resource
 
         self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
 
-    @mock.patch(SSH_HELPER)
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
     def test_wait_for_instantiate_crash(self, ssh):
-        mock_ssh(ssh, exec_result=(1, "", ""))
+        test_base.mock_ssh(ssh, exec_result=(1, "", ""))
 
         mock_process = mock.Mock(autospec=Process)
         mock_process.is_alive.return_value = False
@@ -728,7 +751,7 @@ class TestVpeApproxVnf(unittest.TestCase):
 
         mock_resource = mock.MagicMock()
 
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
         vpe_approx_vnf._vnf_process = mock_process
         vpe_approx_vnf.resource_helper.resource = mock_resource
 
@@ -737,9 +760,9 @@ class TestVpeApproxVnf(unittest.TestCase):
 
         self.assertIn('VNF process died', str(raised.exception))
 
-    @mock.patch(SSH_HELPER)
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
     def test_wait_for_instantiate_panic(self, ssh):
-        mock_ssh(ssh, exec_result=(1, "", ""))
+        test_base.mock_ssh(ssh, exec_result=(1, "", ""))
 
         mock_process = mock.Mock(autospec=Process)
         mock_process.is_alive.return_value = True
@@ -747,7 +770,7 @@ class TestVpeApproxVnf(unittest.TestCase):
 
         mock_resource = mock.MagicMock()
 
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
         vpe_approx_vnf._vnf_process = mock_process
         vpe_approx_vnf.resource_helper.resource = mock_resource
 
@@ -757,9 +780,9 @@ class TestVpeApproxVnf(unittest.TestCase):
 
         self.assertIn('Error starting', str(raised.exception))
 
-    @mock.patch(SSH_HELPER)
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
     def test_wait_for_instantiate_panic_fragmented(self, ssh):
-        mock_ssh(ssh, exec_result=(1, "", ""))
+        test_base.mock_ssh(ssh, exec_result=(1, "", ""))
 
         mock_process = mock.Mock(autospec=Process)
         mock_process.is_alive.return_value = True
@@ -772,7 +795,7 @@ class TestVpeApproxVnf(unittest.TestCase):
 
         mock_resource = mock.MagicMock()
 
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
         vpe_approx_vnf._vnf_process = mock_process
         vpe_approx_vnf.q_out = mock_q_out
         vpe_approx_vnf.resource_helper.resource = mock_resource
@@ -782,11 +805,11 @@ class TestVpeApproxVnf(unittest.TestCase):
 
         self.assertIn('Error starting', str(raised.exception))
 
-    @mock.patch(SSH_HELPER)
+    @mock.patch.object(sample_vnf, 'VnfSshHelper')
     def test_terminate(self, ssh):
-        mock_ssh(ssh)
+        test_base.mock_ssh(ssh)
 
-        vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
+        vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
         vpe_approx_vnf._vnf_process = mock.MagicMock()
         vpe_approx_vnf._resource_collect_stop = mock.Mock()
         vpe_approx_vnf.resource_helper = mock.MagicMock()
index 70d17e2..5eba1a0 100644 (file)
@@ -285,6 +285,23 @@ class ContainerObjectTestCase(base.BaseUnitTestCase):
                     'securityContext': {'key': 'value'}}
         self.assertEqual(expected, container_obj.get_container_item())
 
+    def test_get_container_item_with_env(self):
+        volume_mount = {'name': 'fake_name',
+                        'mountPath': 'fake_path'}
+        args = ['arg1', 'arg2']
+        container_obj = kubernetes.ContainerObject(
+            'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+            args=args, env=[{'name': 'fake_var_name',
+                             'value': 'fake_var_value'}])
+        expected = {'args': args,
+                    'command': [kubernetes.ContainerObject.COMMAND_DEFAULT],
+                    'image': kubernetes.ContainerObject.IMAGE_DEFAULT,
+                    'name': 'cname-container',
+                    'volumeMounts': container_obj._create_volume_mounts(),
+                    'env': [{'name': 'fake_var_name',
+                             'value': 'fake_var_value'}]}
+        self.assertEqual(expected, container_obj.get_container_item())
+
 
 class CustomResourceDefinitionObjectTestCase(base.BaseUnitTestCase):
 
index 57dacbc..5d35209 100644 (file)
@@ -6,60 +6,64 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
-from __future__ import absolute_import
-import unittest
+
+import os
+import sys
+
 import mock
 import uuid
 
-from yardstick.cmd.commands.env import EnvCommand
+from yardstick.cmd.commands import env
+from yardstick.tests.unit import base
 
 
-class EnvCommandTestCase(unittest.TestCase):
+class EnvCommandTestCase(base.BaseUnitTestCase):
 
-    @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task')
-    @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status')
+    @mock.patch.object(env.EnvCommand, '_start_async_task')
+    @mock.patch.object(env.EnvCommand, '_check_status')
     def test_do_influxdb(self, check_status_mock, start_async_task_mock):
-        env = EnvCommand()
-        env.do_influxdb({})
+        _env = env.EnvCommand()
+        _env.do_influxdb({})
         start_async_task_mock.assert_called_once()
         check_status_mock.assert_called_once()
 
-    @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task')
-    @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status')
+    @mock.patch.object(env.EnvCommand, '_start_async_task')
+    @mock.patch.object(env.EnvCommand, '_check_status')
     def test_do_grafana(self, check_status_mock, start_async_task_mock):
-        env = EnvCommand()
-        env.do_grafana({})
+        _env = env.EnvCommand()
+        _env.do_grafana({})
         start_async_task_mock.assert_called_once()
         check_status_mock.assert_called_once()
 
-    @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task')
-    @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status')
+    @mock.patch.object(env.EnvCommand, '_start_async_task')
+    @mock.patch.object(env.EnvCommand, '_check_status')
     def test_do_prepare(self, check_status_mock, start_async_task_mock):
-        env = EnvCommand()
-        env.do_prepare({})
+        _env = env.EnvCommand()
+        _env.do_prepare({})
         start_async_task_mock.assert_called_once()
         check_status_mock.assert_called_once()
 
-    @mock.patch('yardstick.cmd.commands.env.HttpClient.post')
+    @mock.patch.object(env.HttpClient, 'post')
     def test_start_async_task(self, post_mock):
         data = {'action': 'create_grafana'}
-        EnvCommand()._start_async_task(data)
+        env.EnvCommand()._start_async_task(data)
         post_mock.assert_called_once()
 
-    @mock.patch('yardstick.cmd.commands.env.HttpClient.get')
-    @mock.patch('yardstick.cmd.commands.env.EnvCommand._print_status')
-    def test_check_status(self, print_mock, get_mock):
-        # pylint: disable=unused-argument
-        # NOTE(ralonsoh): the pylint exception must be removed. The mocked
-        # command call must be tested.
+    @mock.patch.object(env.HttpClient, 'get')
+    @mock.patch.object(env.EnvCommand, '_print_status')
+    def test_check_status(self, mock_print, mock_get):
         task_id = str(uuid.uuid4())
-        get_mock.return_value = {'status': 2, 'result': 'error'}
-        status = EnvCommand()._check_status(task_id, 'hello world')
-        self.assertEqual(status, 2)
+        mock_get.return_value = {'status': 2, 'result': 'error'}
+        self.assertEqual(
+            2, env.EnvCommand()._check_status(task_id, 'hello world'))
+        self.assertEqual(2, mock_print.call_count)
 
-    def test_print_status(self):
-        try:
-            EnvCommand()._print_status('hello', 'word')
-        except Exception as e:  # pylint: disable=broad-except
-            # NOTE(ralonsoh): try to reduce the scope of this exception.
-            self.assertIsInstance(e, IndexError)
+    @mock.patch.object(sys, 'stdout')
+    @mock.patch.object(os, 'popen')
+    def test_print_status(self, mock_popen, mock_stdout):
+        mock_popen_obj = mock.Mock()
+        mock_popen_obj.read.return_value = ''
+        mock_popen.return_value = mock_popen_obj
+        env.EnvCommand()._print_status('hello', 'word')
+        mock_stdout.write.assert_not_called()
+        mock_stdout.flush.assert_not_called()
index 080d278..b727e82 100644 (file)
@@ -193,10 +193,10 @@ class SSHTestCase(unittest.TestCase):
         with self.assertRaises(exceptions.SSHError) as raised:
             test_ssh._get_client()
 
-        self.assertEqual(mock_paramiko.SSHClient.call_count, 1)
-        self.assertEqual(mock_paramiko.AutoAddPolicy.call_count, 1)
-        self.assertEqual(fake_client.set_missing_host_key_policy.call_count, 1)
-        self.assertEqual(fake_client.connect.call_count, 1)
+        mock_paramiko.SSHClient.assert_called_once()
+        mock_paramiko.AutoAddPolicy.assert_called_once()
+        fake_client.set_missing_host_key_policy.assert_called_once()
+        fake_client.connect.assert_called_once()
         exc_str = str(raised.exception)
         self.assertIn('raised during connect', exc_str)
         self.assertIn('MyError', exc_str)
@@ -238,6 +238,25 @@ class SSHTestCase(unittest.TestCase):
         self.assertEqual("stdout fake data", stdout)
         self.assertEqual("stderr fake data", stderr)
 
+    @mock.patch("yardstick.ssh.six.moves.StringIO")
+    def test_execute_raise_on_error_passed(self, mock_string_io):
+        mock_string_io.side_effect = stdio = [mock.Mock(), mock.Mock()]
+        stdio[0].read.return_value = "stdout fake data"
+        stdio[1].read.return_value = "stderr fake data"
+        with mock.patch.object(self.test_client, "run", return_value=0) \
+                as mock_run:
+            status, stdout, stderr = self.test_client.execute(
+                "cmd",
+                stdin="fake_stdin",
+                timeout=43,
+                raise_on_error=True)
+        mock_run.assert_called_once_with(
+            "cmd", stdin="fake_stdin", stdout=stdio[0],
+            stderr=stdio[1], timeout=43, raise_on_error=True)
+        self.assertEqual(0, status)
+        self.assertEqual("stdout fake data", stdout)
+        self.assertEqual("stderr fake data", stderr)
+
     @mock.patch("yardstick.ssh.time")
     def test_wait_timeout(self, mock_time):
         mock_time.time.side_effect = [1, 50, 150]
@@ -510,7 +529,7 @@ class TestAutoConnectSSH(unittest.TestCase):
         auto_connect_ssh._get_client = mock__get_client = mock.Mock()
 
         auto_connect_ssh._connect()
-        self.assertEqual(mock__get_client.call_count, 1)
+        mock__get_client.assert_called_once()
 
     def test___init___negative(self):
         with self.assertRaises(TypeError):
@@ -543,7 +562,7 @@ class TestAutoConnectSSH(unittest.TestCase):
 
         auto_connect_ssh.get_file_obj('remote/path', mock.Mock())
 
-        self.assertEqual(mock_sftp.getfo.call_count, 1)
+        mock_sftp.getfo.assert_called_once()
 
     def test__make_dict(self):
         auto_connect_ssh = AutoConnectSSH('user1', 'host1')
@@ -580,7 +599,7 @@ class TestAutoConnectSSH(unittest.TestCase):
 
         auto_connect_ssh.put('a', 'z')
         with mock_scp_client_type() as mock_scp_client:
-            self.assertEqual(mock_scp_client.put.call_count, 1)
+            mock_scp_client.put.assert_called_once()
 
     @mock.patch('yardstick.ssh.SCPClient')
     def test_get(self, mock_scp_client_type):
@@ -589,7 +608,7 @@ class TestAutoConnectSSH(unittest.TestCase):
 
         auto_connect_ssh.get('a', 'z')
         with mock_scp_client_type() as mock_scp_client:
-            self.assertEqual(mock_scp_client.get.call_count, 1)
+            mock_scp_client.get.assert_called_once()
 
     def test_put_file(self):
         auto_connect_ssh = AutoConnectSSH('user1', 'host1')
@@ -597,4 +616,4 @@ class TestAutoConnectSSH(unittest.TestCase):
         auto_connect_ssh._put_file_sftp = mock_put_sftp = mock.Mock()
 
         auto_connect_ssh.put_file('a', 'b')
-        self.assertEqual(mock_put_sftp.call_count, 1)
+        mock_put_sftp.assert_called_once()