Merge "Prox L2FWD multiflow test fix"
authorAbhijit Sinha <abhijit.sinha@intel.com>
Wed, 28 Nov 2018 17:26:12 +0000 (17:26 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Wed, 28 Nov 2018 17:26:12 +0000 (17:26 +0000)
39 files changed:
ansible/baremetal_scale_out_ixia_correlated_test.yaml [moved from ansible/multi_port_baremetal_ixia_correlated_test.yaml with 95% similarity]
ansible/baremetal_scale_out_ixia_correlated_test_templates.yml [moved from ansible/multi_port_baremetal_ixia_correlated_test_templates.yml with 69% similarity]
ansible/multi_port_baremetal_ixia_test_templates.yml
ansible/multi_port_baremetal_test_templates.yml
ansible/roles/barometer_collectd/tasks/main.yaml [new file with mode: 0644]
ansible/roles/docker/tasks/Debian.yml
ansible/ubuntu_server_baremetal_deploy_samplevnfs.yml
dashboard/Prox_BM_L3FWD-4Port-1539358774395.json [moved from dashboard/Prox_BM_L3FWD-4Port-1536065939744.json with 94% similarity]
docs/testing/user/userguide/10-yardstick-user-interface.rst
docs/testing/user/userguide/14-nsb-operation.rst
etc/yardstick/nodes/standalone/pod_bm_vnf_scale_out.yaml [new file with mode: 0644]
requirements.txt
samples/vnf_samples/nsut/acl/tc_baremetal_acl_rfc2544_ixia_template.yaml
samples/vnf_samples/nsut/acl/tc_baremetal_acl_rfc2544_template.yaml
samples/vnf_samples/nsut/acl/tc_baremetal_acl_udp_ixia_correlated_multi_port_template.yaml
samples/vnf_samples/nsut/acl/tc_baremetal_acl_udp_ixia_correlated_scale_out_template.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_rfc2544_ixia_template.yaml
samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_rfc2544_template.yaml
samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_udp_ixia_correlated_multi_port_template.yaml
samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_udp_ixia_correlated_scale_out_template.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_rfc2544_ixia_template.yaml
samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_udp_ixia_correlated_multi_port_template.yaml
samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_udp_ixia_correlated_scale_out_template.yaml [new file with mode: 0644]
yardstick/benchmark/contexts/standalone/model.py
yardstick/benchmark/contexts/standalone/ovs_dpdk.py
yardstick/benchmark/core/report.py
yardstick/common/html_template.py
yardstick/common/nsb_report.css [new file with mode: 0644]
yardstick/common/nsb_report.html.j2 [new file with mode: 0644]
yardstick/common/report.html.j2 [new file with mode: 0644]
yardstick/common/utils.py
yardstick/network_services/traffic_profile/prox_binsearch.py
yardstick/network_services/vnf_generic/vnf/prox_helpers.py
yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
yardstick/tests/unit/benchmark/core/test_report.py
yardstick/tests/unit/network_services/traffic_profile/test_prox_binsearch.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2017 Intel Corporation. #
+# 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
       ip:
         mgmt:
           - '1.2.1.6/24'
+          - '1.2.1.7/24'
         uplink:
           - '152.16.100.10/24'
           - '172.16.100.10/24'
           - '00:00:00:9e:00:fb'
 
   tasks:
-    - include: multi_port_baremetal_ixia_correlated_test_templates.yml
+    - include: baremetal_scale_out_ixia_correlated_test_templates.yml
       with_items: "{{ scale_out }}"
 
@@ -1,4 +1,4 @@
-# Copyright (c) 2017 Intel Corporation. #
+# 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
 - set_fact:
     num_vnfs: "{{ item }}"
 
+- file:
+    path: /etc/yardstick/nodes
+    state: directory
+
 - debug:
     var: num_vnfs
     verbosity: 2
     dest: ../samples/vnf_samples/traffic_profiles/ipv4_throughput-ixia-{{ num_vnfs }}.yaml
 
 - template:
-    src: ../etc/yardstick/nodes/standalone/ixia_template.yaml
-    dest: /etc/yardstick/nodes/ixia_{{ num_vnfs }}.yaml
+    src: ../etc/yardstick/nodes/standalone/ixia_correlated_template.yaml
+    dest: /etc/yardstick/nodes/ixia_correlated_{{ num_vnfs }}.yaml
 
 - template:
-    src: ../etc/yardstick/nodes/standalone/pod_bm_vnf.yaml
+    src: ../etc/yardstick/nodes/standalone/pod_bm_vnf_scale_out.yaml
     dest: /etc/yardstick/nodes/pod_bm_vnf_{{num_vnfs}}.yaml
 
 - template:
-    src: ../samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_udp_ixia_correlated_multi_port_template.yaml
-    dest: ../samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_udp_ixia_correlated_multi_port_{{ num_vnfs }}.yaml
+    src: ../samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_udp_ixia_correlated_scale_out_template.yaml
+    dest: ../samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_udp_ixia_correlated_scale_out_{{ num_vnfs }}.yaml
 
 - template:
-     src: ../samples/vnf_samples/nsut/vfw/vfw-tg-topology-ixia-correlated-multi-port.yaml
-     dest: ../samples/vnf_samples/nsut/vfw/vfw-tg-topology-ixia-correlated-multi-port-{{ num_vnfs }}.yaml
+     src: ../samples/vnf_samples/nsut/vfw/vfw-tg-topology-ixia-correlated-scale-out.yaml
+     dest: ../samples/vnf_samples/nsut/vfw/vfw-tg-topology-ixia-correlated-scale-out-{{ num_vnfs }}.yaml
 
 - template:
-    src: ../samples/vnf_samples/nsut/acl/tc_baremetal_acl_udp_ixia_correlated_multi_port_template.yaml
-    dest: ../samples/vnf_samples/nsut/acl/tc_baremetal_acl_udp_ixia_correlated_multi_port_{{num_vnfs}}.yaml
+    src: ../samples/vnf_samples/nsut/acl/tc_baremetal_acl_udp_ixia_correlated_scale_out_template.yaml
+    dest: ../samples/vnf_samples/nsut/acl/tc_baremetal_acl_udp_ixia_correlated_scale_out_{{num_vnfs}}.yaml
 
 - template:
-     src: ../samples/vnf_samples/nsut/acl/acl-tg-topology-ixia-correlated-multi-port.yaml
-     dest: ../samples/vnf_samples/nsut/acl/acl-tg-topology-ixia-correlated-multi-port-{{ num_vnfs }}.yaml
+     src: ../samples/vnf_samples/nsut/acl/acl-tg-topology-ixia-correlated-scale-out.yaml
+     dest: ../samples/vnf_samples/nsut/acl/acl-tg-topology-ixia-correlated-scale-out-{{ num_vnfs }}.yaml
 
 - template:
-    src: ../samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_udp_ixia_correlated_multi_port_template.yaml
-    dest: ../samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_udp_ixia_correlated_multi_port_{{num_vnfs}}.yaml
+    src: ../samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_udp_ixia_correlated_scale_out_template.yaml
+    dest: ../samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_udp_ixia_correlated_scale_out_{{num_vnfs}}.yaml
 
 - template:
-     src: ../samples/vnf_samples/nsut/cgnapt/cgnapt-tg-topology-ixia-correlated-multi-port.yaml
-     dest: ../samples/vnf_samples/nsut/cgnapt/cgnapt-tg-topology-ixia-correlated-multi-port-{{ num_vnfs }}.yaml
+     src: ../samples/vnf_samples/nsut/cgnapt/cgnapt-tg-topology-ixia-correlated-scale-out.yaml
+     dest: ../samples/vnf_samples/nsut/cgnapt/cgnapt-tg-topology-ixia-correlated-scale-out-{{ num_vnfs }}.yaml
index f2e04a2..832f025 100644 (file)
 - set_fact:
     num_vnfs: "{{ item }}"
 
+- file:
+    path: /etc/yardstick/nodes
+    state: directory
+
 - debug:
     var: num_vnfs
     verbosity: 2
 
 - template:
     src: ../etc/yardstick/nodes/standalone/ixia_template.yaml
-    dest: /etc/yardstick/nodes/ixia_{{ num_vnfs }}.yaml
+    dest: /etc/yardstick/nodes/baremetal_ixia_{{ num_vnfs }}.yaml
 
 - template:
     src: ../etc/yardstick/nodes/standalone/pod_bm_vnf.yaml
     dest: /etc/yardstick/nodes/pod_bm_vnf_{{num_vnfs}}.yaml
 
 - template:
-    src: ../samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_rfc2544_template.yaml
-    dest: ../samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_rfc2544_{{ num_vnfs }}.yaml
+    src: ../samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_rfc2544_ixia_template.yaml
+    dest: ../samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_rfc2544_ixia_{{ num_vnfs }}.yaml
 
 - template:
      src: ../samples/vnf_samples/nsut/vfw/vfw-tg-topology-ixia-multi-port.yaml
@@ -45,7 +49,7 @@
 
 - template:
      src: ../samples/vnf_samples/nsut/acl/acl-tg-topology-ixia-multi-port.yaml
-     dest: ../samples/vnf_samples/nsut/acl/acl-tg-topology-multi-port-ixia-{{ num_vnfs }}.yaml
+     dest: ../samples/vnf_samples/nsut/acl/acl-tg-topology-ixia-multi-port-{{ num_vnfs }}.yaml
 
 - template:
     src: ../samples/vnf_samples/traffic_profiles/ipv4_throughput-cgnapt-scale-out.yaml
index 4b905f8..2d02593 100644 (file)
 - set_fact:
     num_vnfs: "{{ item }}"
 
+- file:
+    path: /etc/yardstick/nodes
+    state: directory
+
 - debug:
     var: num_vnfs
     verbosity: 2
@@ -40,8 +44,8 @@
      dest: ../samples/vnf_samples/nsut/vfw/vfw-tg-topology-multi-port-{{ num_vnfs }}.yaml
 
 - template:
-    src: ../samples/vnf_samples/nsut/acl/tc_baremetal_vfw_rfc2544_template.yaml
-    dest: ../samples/vnf_samples/nsut/acl/tc_baremetal_vfw_rfc2544_{{ num_vnfs }}.yaml
+    src: ../samples/vnf_samples/nsut/acl/tc_baremetal_acl_rfc2544_template.yaml
+    dest: ../samples/vnf_samples/nsut/acl/tc_baremetal_acl_rfc2544_{{ num_vnfs }}.yaml
 
 - template:
      src: ../samples/vnf_samples/nsut/acl/acl-tg-topology-multi-port.yaml
@@ -52,8 +56,8 @@
     dest: ../samples/vnf_samples/traffic_profiles/ipv4_throughput-cgnapt-{{ num_vnfs }}.yaml
 
 - template:
-    src: ../samples/vnf_samples/nsut/cgnapt/tc_baremetal_vfw_rfc2544_template.yaml
-    dest: ../samples/vnf_samples/nsut/cgnapt/tc_baremetal_vfw_rfc2544_{{ num_vnfs }}.yaml
+    src: ../samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_rfc2544_template.yaml
+    dest: ../samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_rfc2544_{{ num_vnfs }}.yaml
 
 - template:
      src: ../samples/vnf_samples/nsut/cgnapt/cgnapt-tg-topology-multi-port.yaml
diff --git a/ansible/roles/barometer_collectd/tasks/main.yaml b/ansible/roles/barometer_collectd/tasks/main.yaml
new file mode 100644 (file)
index 0000000..c06540c
--- /dev/null
@@ -0,0 +1,40 @@
+#Copyright 2018 OPNFV and 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: Remove barometer-collectd container
+  docker_container:
+    name: barometer-collectd
+    state: absent
+
+- name: Remove barometer-collectd image
+  docker_image:
+    name: opnfv/barometer-collectd
+    state: absent
+
+- name: Prepare collectd container
+  docker_container:
+    name: barometer-collectd
+    image: opnfv/barometer-collectd
+    volumes:
+       - /opt/collectd/etc/collectd.conf.d/:/opt/collectd/etc/collectd.conf.d
+       - /var/run:/var/run
+       - /tmp:/tmp
+       - /var/lib/collectd:/var/lib/collectd
+    command: "/run_collectd.sh"
+    detach: yes
+    state: present
+    restart: no
+    privileged: yes
+    network_mode: host
index 7f998de..a03040d 100644 (file)
 ---
   - name: Install docker.io
     action: "{{ ansible_pkg_mgr }} name=docker.io state=present force=yes"
+
+  - name: Update package manager cache
+    tags:
+       - cache_update
+    package:
+       update_cache: yes
+
+  - name: Install python-pip
+    package:
+       name: python-pip
+       state: present
+
+  - name: Install docker-py
+    pip:
+       name: docker-py
+       state: present
index 3a29a8a..b69fb58 100644 (file)
@@ -54,3 +54,5 @@
     - install_pmu_tools
     - download_collectd
     - install_collectd
+    - docker
+    - barometer_collectd
@@ -14,7 +14,7 @@
       "type": "grafana",
       "id": "grafana",
       "name": "Grafana",
-      "version": "4.6.3"
+      "version": "4.4.3"
     },
     {
       "type": "panel",
@@ -60,7 +60,7 @@
   "hideControls": false,
   "id": null,
   "links": [],
-  "refresh": false,
+  "refresh": "5s",
   "rows": [
     {
       "collapse": false,
             "max": true,
             "min": true,
             "show": true,
-            "sortDesc": true,
+            "sort": null,
+            "sortDesc": null,
             "total": false,
             "values": true
           },
           "fill": 1,
           "grid": {},
           "height": "300px",
-          "id": 2,
+          "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": 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.collect_stats.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: Average Throughout per step",
+          "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
+            }
+          ]
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "${DS_YARDSTICK}",
+          "editable": true,
+          "error": false,
+          "fill": 1,
+          "grid": {},
+          "height": "300px",
+          "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": 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.collect_stats.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": 2,
+              "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": 169,
+      "panels": [
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "${DS_YARDSTICK}",
+          "decimals": 4,
+          "editable": true,
+          "error": false,
+          "fill": 1,
+          "grid": {},
+          "height": "300px",
+          "id": 206,
+          "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": true,
+          "targets": [
+            {
+              "alias": "TG xe-0 Out packets",
+              "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 mean(\"tg__0.collect_stats.xe0.out_packets\")  / 1000000 FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
+              "rawQuery": false,
+              "refId": "A",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "tg__0.collect_stats.live_stats.xe0.out_packets"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "TG xe-1 Out packets",
+              "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 mean(\"tg__0.collect_stats.live_stats.xe1.out_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
+              "rawQuery": false,
+              "refId": "B",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "tg__0.collect_stats.live_stats.xe1.out_packets"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
+                  }
+                ]
+              ],
+              "tags": []
+            },
+            {
+              "alias": "TG xe-2 Out packets",
+              "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 mean(\"tg__0.collect_stats.xe2.out_packets\")  / 1000000 FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
+              "rawQuery": false,
+              "refId": "C",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "tg__0.collect_stats.live_stats.xe2.out_packets"
+                    ],
+                    "type": "field"
+                  },
+                  {
+                    "params": [],
+                    "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
+                  }
+                ]
+              ],
+              "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",
+              "query": "SELECT mean(\"tg__0.collect_stats.xe3.out_packets\")  / 1000000 FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
+              "rawQuery": false,
+              "refId": "D",
+              "resultFormat": "time_series",
+              "select": [
+                [
+                  {
+                    "params": [
+                      "tg__0.collect_stats.live_stats.xe3.out_packets"
+                    ],
+                    "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": "Packets Sent by Generator per second and per interface",
+          "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
+            }
+          ]
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "${DS_YARDSTICK}",
+          "decimals": 4,
+          "editable": true,
+          "error": false,
+          "fill": 1,
+          "grid": {},
+          "height": "300px",
+          "id": 207,
           "legend": {
             "alignAsTable": true,
             "avg": true,
           "spaceLength": 10,
           "span": 6,
           "stack": false,
-          "steppedLine": true,
+          "steppedLine": false,
           "targets": [
             {
-              "alias": "Load Requested to Generator",
+              "alias": "TG xe-0 in packets",
               "dsType": "influxdb",
               "groupBy": [
                 {
               "measurement": "tc_prox_baremetal_l3fwd-4",
               "orderByTime": "ASC",
               "policy": "default",
+              "query": "SELECT mean(\"tg__0.collect_stats.xe0.in_packets\")  / 1000000 FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
+              "rawQuery": false,
               "refId": "A",
               "resultFormat": "time_series",
               "select": [
                 [
                   {
                     "params": [
-                      "tg__0.collect_stats.RequestedTxThroughput"
+                      "tg__0.collect_stats.live_stats.xe0.in_packets"
                     ],
                     "type": "field"
                   },
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
               "tags": []
             },
             {
-              "alias": "Load Generated (by the Generator)",
+              "alias": "TG xe-1 in packets",
               "dsType": "influxdb",
               "groupBy": [
                 {
               "measurement": "tc_prox_baremetal_l3fwd-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "refId": "A",
+              "query": "SELECT mean(\"tg__0.collect_stats.live_stats.xe1.in_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
+              "rawQuery": false,
+              "refId": "B",
               "resultFormat": "time_series",
               "select": [
                 [
                   {
                     "params": [
-                      "tg__0.TxThroughput"
+                      "tg__0.collect_stats.live_stats.xe1.in_packets"
                     ],
                     "type": "field"
                   },
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
               "tags": []
             },
             {
-              "alias": "Load Received (by the Generator)",
+              "alias": "TG xe-2 in packets",
               "dsType": "influxdb",
               "groupBy": [
                 {
                   "type": "fill"
                 }
               ],
-              "hide": false,
               "measurement": "tc_prox_baremetal_l3fwd-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "refId": "B",
+              "query": "SELECT mean(\"tg__0.collect_stats.live_stats.xe2.in_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
+              "rawQuery": false,
+              "refId": "C",
               "resultFormat": "time_series",
               "select": [
                 [
                   {
                     "params": [
-                      "tg__0.RxThroughput"
+                      "tg__0.collect_stats.live_stats.xe2.in_packets"
                     ],
                     "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": "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
-            }
-          ]
-        },
-        {
-          "aliasColors": {},
-          "bars": false,
-          "dashLength": 10,
-          "dashes": false,
-          "datasource": "${DS_YARDSTICK}",
-          "editable": true,
-          "error": false,
-          "fill": 1,
-          "grid": {},
-          "height": "300px",
-          "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": true,
-          "targets": [
-            {
-              "alias": "Packet Size",
+              "alias": "TG xe-3 in packets",
               "dsType": "influxdb",
               "groupBy": [
                 {
               "measurement": "tc_prox_baremetal_l3fwd-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "refId": "A",
+              "query": "SELECT mean(\"tg__0.collect_stats.live_stats.xe3.in_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
+              "rawQuery": false,
+              "refId": "D",
               "resultFormat": "time_series",
               "select": [
                 [
                   {
                     "params": [
-                      "tg__0.collect_stats.PktSize"
+                      "tg__0.collect_stats.live_stats.xe3.in_packets"
                     ],
                     "type": "field"
                   },
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
           ],
           "timeFrom": null,
           "timeShift": null,
-          "title": "Packet size",
+          "title": "Packets Received by Generator per second and per interface",
           "tooltip": {
             "msResolution": true,
             "shared": true,
           },
           "yaxes": [
             {
-              "format": "none",
-              "label": "Packet Size (Bytes)",
-              "logBase": 2,
+              "format": "short",
+              "label": "Million Packets Per Second",
+              "logBase": 1,
               "max": null,
-              "min": null,
+              "min": "0",
               "show": true
             },
             {
               "show": true
             }
           ]
-        }
-      ],
-      "repeat": null,
-      "repeatIteration": null,
-      "repeatRowId": null,
-      "showTitle": false,
-      "title": "New row",
-      "titleSize": "h6"
-    },
-    {
-      "collapse": false,
-      "height": 169,
-      "panels": [
+        },
         {
           "aliasColors": {},
           "bars": false,
             "min": true,
             "rightSide": false,
             "show": true,
-            "sortDesc": true,
+            "sortDesc": false,
             "total": false,
             "values": true
           },
           ]
         },
         {
-          "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>Generator Stats: Packets per Step</center> </a></h5>\n",
           "editable": true,
           "error": false,
           "height": "40",
                   "type": "fill"
                 }
               ],
+              "hide": false,
               "measurement": "tc_prox_baremetal_l3fwd-4",
               "orderByTime": "ASC",
               "policy": "default",
               "query": "SELECT mean(\"tg__0.collect_stats.xe0.out_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
-              "rawQuery": true,
+              "rawQuery": false,
               "refId": "A",
               "resultFormat": "time_series",
               "select": [
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
                   "type": "fill"
                 }
               ],
+              "hide": false,
               "measurement": "tc_prox_baremetal_l3fwd-4",
               "orderByTime": "ASC",
               "policy": "default",
               "query": "SELECT mean(\"tg__0.collect_stats.xe1.out_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
-              "rawQuery": true,
+              "rawQuery": false,
               "refId": "B",
               "resultFormat": "time_series",
               "select": [
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
                   "type": "fill"
                 }
               ],
+              "hide": false,
               "measurement": "tc_prox_baremetal_l3fwd-4",
               "orderByTime": "ASC",
               "policy": "default",
               "query": "SELECT mean(\"tg__0.collect_stats.xe2.out_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
-              "rawQuery": true,
+              "rawQuery": false,
               "refId": "C",
               "resultFormat": "time_series",
               "select": [
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
               "orderByTime": "ASC",
               "policy": "default",
               "query": "SELECT mean(\"tg__0.collect_stats.xe3.out_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
-              "rawQuery": true,
+              "rawQuery": false,
               "refId": "D",
               "resultFormat": "time_series",
               "select": [
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
           ],
           "timeFrom": null,
           "timeShift": null,
-          "title": "Packets Sent by Generator",
+          "title": "Packets Sent by Generator per Step",
           "tooltip": {
             "msResolution": true,
             "shared": true,
           "yaxes": [
             {
               "format": "short",
-              "label": "Packets ",
+              "label": "Million Packets  Per Step",
               "logBase": 1,
               "max": null,
               "min": "0",
           "dashLength": 10,
           "dashes": false,
           "datasource": "${DS_YARDSTICK}",
+          "decimals": 4,
           "editable": true,
           "error": false,
           "fill": 1,
             "max": true,
             "min": true,
             "show": true,
+            "sortDesc": true,
             "total": false,
             "values": true
           },
               "orderByTime": "ASC",
               "policy": "default",
               "query": "SELECT mean(\"tg__0.collect_stats.xe0.in_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
-              "rawQuery": true,
+              "rawQuery": false,
               "refId": "A",
               "resultFormat": "time_series",
               "select": [
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
               "orderByTime": "ASC",
               "policy": "default",
               "query": "SELECT mean(\"tg__0.collect_stats.xe1.in_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
-              "rawQuery": true,
+              "rawQuery": false,
               "refId": "B",
               "resultFormat": "time_series",
               "select": [
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
               "orderByTime": "ASC",
               "policy": "default",
               "query": "SELECT mean(\"tg__0.collect_stats.xe2.in_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
-              "rawQuery": true,
+              "rawQuery": false,
               "refId": "C",
               "resultFormat": "time_series",
               "select": [
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
               "orderByTime": "ASC",
               "policy": "default",
               "query": "SELECT mean(\"tg__0.collect_stats.xe3.in_packets\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
-              "rawQuery": true,
+              "rawQuery": false,
               "refId": "D",
               "resultFormat": "time_series",
               "select": [
                   {
                     "params": [],
                     "type": "mean"
+                  },
+                  {
+                    "params": [
+                      " / 1000000"
+                    ],
+                    "type": "math"
                   }
                 ]
               ],
           ],
           "timeFrom": null,
           "timeShift": null,
-          "title": "Packets Received by Generator",
+          "title": "Packets Received by Generator per Step",
           "tooltip": {
             "msResolution": true,
             "shared": true,
           "yaxes": [
             {
               "format": "short",
-              "label": "Packets Per Second",
+              "label": "Million Packets Per Step",
               "logBase": 1,
               "max": null,
               "min": "0",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
               "measurement": "tc_prox_baremetal_l3fwd-4",
               "orderByTime": "ASC",
               "policy": "default",
-              "query": "SELECT  last(\"tg__0.collect_stats.theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.collect_stats.PktSize\" = 64 AND \"tg__0.collect_stats.Status\" = 'Result' AND $timeFilter GROUP BY time($__interval) fill(null)",
+              "query": "SELECT  last(\"tg__0.collect_stats.theor_max_throughput\") FROM \"tc_prox_baremetal_l3fwd-4\" WHERE \"tg__0.collect_stats.PktSize\" = 64  AND \"tg__0.collect_stats.Status\" = 'Result' AND $timeFilter GROUP BY time($__interval) fill(null)",
               "rawQuery": true,
               "refId": "A",
               "resultFormat": "time_series",
                 [
                   {
                     "params": [
-                      "tg__0.collect_stats.theor_max_throughput"
+                      "tg__0.collect_stats.RequestedTxThroughput"
                     ],
                     "type": "field"
                   },
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
           "thresholds": "",
           "title": "",
           "type": "singlestat",
-          "valueFontSize": "50%",
+          "valueFontSize": "30%",
           "valueMaps": [
             {
               "op": "=",
     "list": []
   },
   "time": {
-    "from": "2018-09-04T00:52:16.948Z",
-    "to": "2018-09-04T12:52:16.948Z"
+    "from": "now-3h",
+    "to": "now"
   },
   "timepicker": {
     "refresh_intervals": [
   },
   "timezone": "browser",
   "title": "Prox_BM_L3FWD-4Port",
-  "version": 3
+  "version": 6
 }
\ No newline at end of file
index cadec78..76890b2 100644 (file)
@@ -16,15 +16,19 @@ Command
 Description
 ===========
 
-1. When the command is triggered using the task-id and the testcase
-name provided the respective values are retrieved from the
-database (influxdb in this particular case).
+1. When the command is triggered, the relevant values for the
+   provided task-id and testcase name are retrieved from the
+   database (`InfluxDB`_ in this particular case).
 
-2. The values are then formatted and then provided to the html
-template framed with complete html body using Django Framework.
+2. The values are then formatted and provided to the html
+   template to be rendered using `Jinja2`_.
 
-3. Then the whole template is written into a html file.
+3. Then the rendered template is written into a html file.
 
 The graph is framed with Timestamp on x-axis and output values
 (differ from testcase to testcase) on y-axis with the help of
-"Highcharts".
+`Highcharts`_.
+
+.. _InfluxDB: https://www.influxdata.com/time-series-platform/influxdb/
+.. _Jinja2: http://jinja.pocoo.org/docs/2.10/
+.. _Highcharts: https://www.highcharts.com/products/highcharts/
index c961558..7ec5b4e 100644 (file)
@@ -434,6 +434,43 @@ 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.
 
+Emulated machine type
+^^^^^^^^^^^^^^^^^^^^^
+
+For better performance test results of emulated VM spawned by Yardstick SA
+context (OvS-DPDK/SRIOV), it may be important to control the emulated machine
+type used by QEMU emulator. This attribute can be configured via TC definition
+in ``contexts`` section under ``extra_specs`` configuration.
+
+For example:
+
+.. code-block:: yaml
+
+  contexts:
+     ...
+     - type: StandaloneSriov
+       ...
+       flavor:
+         ...
+         extra_specs:
+           ...
+           machine_type: pc-i440fx-bionic
+
+Where, ``machine_type`` can be set to one of the emulated machine type
+supported by QEMU running on SUT platform. To get full list of supported
+emulated machine types, the following command can be used on the target SUT
+host.
+
+.. code-block:: yaml
+
+  # qemu-system-x86_64 -machine ?
+
+By default, the ``machine_type`` option is set to ``pc-i440fx-xenial`` which is
+suitable for running Ubuntu 16.04 VM image. So, if this type is not supported
+by the target platform or another VM image is used for stand alone (SA) context
+VM (e.g.: ``bionic`` image for Ubuntu 18.04), this configuration should be
+changed accordingly.
+
 Standalone with OVS-DPDK
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/etc/yardstick/nodes/standalone/pod_bm_vnf_scale_out.yaml b/etc/yardstick/nodes/standalone/pod_bm_vnf_scale_out.yaml
new file mode 100644 (file)
index 0000000..b48a049
--- /dev/null
@@ -0,0 +1,37 @@
+# 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.
+
+nodes:
+{% for num in range(num_vnfs|int) %}
+-
+    name: vnf__{{ num }}
+    role: vnf__{{ num }}
+    ip: {{vnf.ip.mgmt[num] | ipaddr('address')}}
+    user: {{vnf.user}}
+    password: {{vnf.password}}
+    key_filename: {{vnf.key_filename}}
+    interfaces:
+       xe0:  # logical name from topology.yaml and vnfd.yaml
+           vpci:      "{{vnf.pcis.uplink[num]}}"
+           dpdk_port_num: 0
+           local_ip: "{{vnf.ip.uplink[num] | ipaddr('address')}}"
+           netmask: "{{vnf.ip.uplink[num] | ipaddr('netmask')}}"
+           local_mac:   "{{vnf.mac.uplink[num]}}"
+       xe1:  # logical name from topology.yaml and vnfd.yaml
+           vpci:      "{{vnf.pcis.downlink[num]}}"
+           dpdk_port_num: 1
+           local_ip: "{{vnf.ip.downlink[num] | ipaddr('address') }}"
+           netmask: "{{vnf.ip.downlink[num] | ipaddr('netmask')}}"
+           local_mac:   "{{vnf.mac.downlink[num]}}"
+{% endfor %}
index 43d7120..43a6c7f 100644 (file)
@@ -15,9 +15,6 @@ ansible==2.5.5          # GPLv3; OSI Approved  GNU General Public License v3 or
 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
-django==1.8.17          # BSD; OSI Approved  BSD License
-                        # NOTE(ralonsoh): django must be bumped to 1.11.8; consider the migration notes [1]
-                        # [1] https://docs.djangoproject.com/ja/1.11/ref/templates/upgrading/
 docker-py==1.10.6       # OSI Approved  Apache Software License
 extras==1.0.0           # OSI Approved  MIT License
 flasgger==0.5.13        # MIT
index 8c7651b..9115507 100644 (file)
@@ -48,7 +48,7 @@ scenarios:
 contexts:
    - name: yardstick
      type: Node
-     file: /etc/yardstick/nodes/baremetal_trex_{{num_vnfs}}.yaml
+     file: /etc/yardstick/nodes/baremetal_ixia_{{num_vnfs}}.yaml
    - name: yardstick
      type: Node
      file: /etc/yardstick/nodes/pod_bm_vnf_{{num_vnfs}}.yaml
index 1333b27..8ba8368 100644 (file)
@@ -17,7 +17,7 @@ schema: yardstick:task:0.1
 scenarios:
   - type: NSPerf
     traffic_profile: ../../traffic_profiles/ipv4_throughput-{{ num_vnfs }}.yaml
-    topology: acl-tg-topology-scale-out-{{ num_vnfs }}.yaml
+    topology: acl-tg-topology-multi-port-{{ num_vnfs }}.yaml
     nodes:
       tg__0: tg__0.yardstick
       vnf__0: vnf__0.yardstick
index da1c5a7..e3558b8 100644 (file)
@@ -42,7 +42,6 @@ scenarios:
       vnf__0:
         rules: acl_1rule.yaml
         vnf_config: {lb_config: '{{flow.vnf_config.lb_config}}', lb_count: {{flow.vnf_config.lb_count}} , worker_config: '{{flow.vnf_config.worker_config}}', worker_threads: {{flow.vnf_config.worker_threads}}}
-
     runner:
       type: Iteration
       iterations: 10
diff --git a/samples/vnf_samples/nsut/acl/tc_baremetal_acl_udp_ixia_correlated_scale_out_template.yaml b/samples/vnf_samples/nsut/acl/tc_baremetal_acl_udp_ixia_correlated_scale_out_template.yaml
new file mode 100644 (file)
index 0000000..55ff62d
--- /dev/null
@@ -0,0 +1,60 @@
+# 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.
+
+---
+schema: yardstick:task:0.1
+scenarios:
+  - type: NSPerf
+    traffic_profile: ../../traffic_profiles/ipv4_throughput-ixia-{{ num_vnfs }}.yaml
+    topology: acl-tg-topology-ixia-correlated-scale-out-{{ num_vnfs }}.yaml
+    nodes:
+      tg__0: tg__0.yardstick
+      tg__1: tg__1.yardstick
+{% for vnf_num in range(num_vnfs|int) %}
+      vnf__{{ vnf_num }}: vnf_{{ vnf_num }}.yardstick
+{% endfor %}
+    options:
+      framesize:
+        uplink: {{ flow.pkt_size.uplink | to_yaml }}
+        downlink: {{ flow.pkt_size.downlink | to_yaml }}
+      flow:
+        src_ip:
+{% for vnf_num in range(num_vnfs|int) %}
+          - {'tg__0': 'xe{{ vnf_num }}'}
+{% endfor %}
+        dst_ip:
+{% for vnf_num in range(num_vnfs|int) %}
+          - {'tg__1': 'xe{{ vnf_num }}'}
+{% endfor %}
+        count: {{ flow.count }}
+      traffic_type: {{ flow.traffic_type }}
+      rfc2544:
+        allowed_drop_rate: {{ flow.rfc2544.allowed_drop_rate }}
+        correlated_traffic: true
+      vnf__0:
+        rules: acl_1rule.yaml
+        vnf_config: {lb_config: '{{flow.vnf_config.lb_config}}', lb_count: {{flow.vnf_config.lb_count}} , worker_config: '{{flow.vnf_config.worker_config}}', worker_threads: {{flow.vnf_config.worker_threads}}}
+    ixia_profile: ../../traffic_profiles/ixia/ixia_ipv4_profile_{{ num_vnfs * 2 }}_port.ixncfg
+
+    runner:
+      type: Iteration
+      iterations: 10
+      interval: 35
+contexts:
+   - name: yardstick
+     type: Node
+     file: /etc/yardstick/nodes/ixia_correlated_{{num_vnfs}}.yaml
+   - type: Node
+     file: /etc/yardstick/nodes/pod_bm_vnf_{{num_vnfs}}.yaml
+     name: yardstick
index 7784947..deb28dc 100644 (file)
@@ -17,7 +17,7 @@ schema: yardstick:task:0.1
 scenarios:
   - type: NSPerf
     traffic_profile: ../../traffic_profiles/ipv4_throughput-{{ num_vnfs }}.yaml
-    topology: cgnapt-tg-topology-ixia-multi-port-{{ num_vnfs }}.yaml
+    topology: cgnapt-tg-topology-multi-port-ixia-{{ num_vnfs }}.yaml
     nodes:
       tg__0: tg__0.yardstick
       vnf__0: vnf__0.yardstick
@@ -39,7 +39,6 @@ scenarios:
       rfc2544:
         allowed_drop_rate: {{ flow.rfc2544.allowed_drop_rate }}
       vnf__0:
-        rules: acl_1rule.yaml
         vnf_config: {lb_config: '{{flow.vnf_config.lb_config}}', lb_count: {{flow.vnf_config.lb_count}} , worker_config: '{{flow.vnf_config.worker_config}}', worker_threads: {{flow.vnf_config.worker_threads}}}
     runner:
       type: Iteration
@@ -48,7 +47,7 @@ scenarios:
 contexts:
    - name: yardstick
      type: Node
-     file: /etc/yardstick/nodes/baremetal_trex_{{num_vnfs}}.yaml
+     file: /etc/yardstick/nodes/baremetal_ixia_{{num_vnfs}}.yaml
    - name: yardstick
      type: Node
      file: /etc/yardstick/nodes/pod_bm_vnf_{{num_vnfs}}.yaml
index 81000a7..f52b41b 100644 (file)
@@ -39,7 +39,6 @@ scenarios:
       rfc2544:
         allowed_drop_rate: {{ flow.rfc2544.allowed_drop_rate }}
       vnf__0:
-        rules: acl_1rule.yaml
         vnf_config: {lb_config: '{{flow.vnf_config.lb_config}}', lb_count: {{flow.vnf_config.lb_count}} , worker_config: '{{flow.vnf_config.worker_config}}', worker_threads: {{flow.vnf_config.worker_threads}}}
     runner:
       type: Iteration
index 0621f9a..198c847 100644 (file)
@@ -40,9 +40,7 @@ scenarios:
       rfc2544:
         allowed_drop_rate: {{ flow.rfc2544.allowed_drop_rate }}
       vnf__0:
-        rules: acl_1rule.yaml
         vnf_config: {lb_config: '{{flow.vnf_config.lb_config}}', lb_count: {{flow.vnf_config.lb_count}} , worker_config: '{{flow.vnf_config.worker_config}}', worker_threads: {{flow.vnf_config.worker_threads}}}
-
     runner:
       type: Iteration
       iterations: 10
diff --git a/samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_udp_ixia_correlated_scale_out_template.yaml b/samples/vnf_samples/nsut/cgnapt/tc_baremetal_cgnapt_udp_ixia_correlated_scale_out_template.yaml
new file mode 100644 (file)
index 0000000..c093608
--- /dev/null
@@ -0,0 +1,59 @@
+# 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.
+
+---
+schema: yardstick:task:0.1
+scenarios:
+  - type: NSPerf
+    traffic_profile: ../../traffic_profiles/ipv4_throughput-ixia-{{ num_vnfs }}.yaml
+    topology: cgnapt-tg-topology-ixia-correlated-scale-out-{{ num_vnfs }}.yaml
+    nodes:
+      tg__0: tg__0.yardstick
+      tg__1: tg__1.yardstick
+{% for vnf_num in range(num_vnfs|int) %}
+      vnf__{{ vnf_num }}: vnf_{{ vnf_num }}.yardstick
+{% endfor %}
+    options:
+      framesize:
+        uplink: {{ flow.pkt_size.uplink | to_yaml }}
+        downlink: {{ flow.pkt_size.downlink | to_yaml }}
+      flow:
+        src_ip:
+{% for vnf_num in range(num_vnfs|int) %}
+          - {'tg__0': 'xe{{ vnf_num }}'}
+{% endfor %}
+        dst_ip:
+{% for vnf_num in range(num_vnfs|int) %}
+          - {'tg__1': 'xe{{ vnf_num }}'}
+{% endfor %}
+        count: {{ flow.count }}
+      traffic_type: {{ flow.traffic_type }}
+      rfc2544:
+        allowed_drop_rate: {{ flow.rfc2544.allowed_drop_rate }}
+        correlated_traffic: true
+      vnf__0:
+        vnf_config: {lb_config: '{{flow.vnf_config.lb_config}}', lb_count: {{flow.vnf_config.lb_count}} , worker_config: '{{flow.vnf_config.worker_config}}', worker_threads: {{flow.vnf_config.worker_threads}}}
+    ixia_profile: ../../traffic_profiles/ixia/ixia_ipv4_profile_{{ num_vnfs * 2}}_port.ixncfg
+
+    runner:
+      type: Iteration
+      iterations: 10
+      interval: 35
+contexts:
+   - name: yardstick
+     type: Node
+     file: /etc/yardstick/nodes/ixia_correlated_{{num_vnfs}}.yaml
+   - type: Node
+     file: /etc/yardstick/nodes/pod_bm_vnf_{{num_vnfs}}.yaml
+     name: yardstick
index 96a079b..28e3216 100644 (file)
@@ -48,7 +48,7 @@ scenarios:
 contexts:
    - name: yardstick
      type: Node
-     file: /etc/yardstick/nodes/baremetal_trex_{{num_vnfs}}.yaml
+     file: /etc/yardstick/nodes/baremetal_ixia_{{num_vnfs}}.yaml
    - name: yardstick
      type: Node
      file: /etc/yardstick/nodes/pod_bm_vnf_{{num_vnfs}}.yaml
index 43803d3..462d14f 100644 (file)
@@ -42,7 +42,6 @@ scenarios:
       vnf__0:
         rules: acl_1rule.yaml
         vnf_config: {lb_config: '{{flow.vnf_config.lb_config}}', lb_count: {{flow.vnf_config.lb_count}} , worker_config: '{{flow.vnf_config.worker_config}}', worker_threads: {{flow.vnf_config.worker_threads}}}
-
     runner:
       type: Iteration
       iterations: 10
diff --git a/samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_udp_ixia_correlated_scale_out_template.yaml b/samples/vnf_samples/nsut/vfw/tc_baremetal_vfw_udp_ixia_correlated_scale_out_template.yaml
new file mode 100644 (file)
index 0000000..77d0bf8
--- /dev/null
@@ -0,0 +1,60 @@
+# 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.
+
+---
+schema: yardstick:task:0.1
+scenarios:
+  - type: NSPerf
+    traffic_profile: ../../traffic_profiles/ipv4_throughput-ixia-{{ num_vnfs }}.yaml
+    topology: vfw-tg-topology-ixia-correlated-scale-out-{{ num_vnfs }}.yaml
+    nodes:
+      tg__0: tg__0.yardstick
+      tg__1: tg__1.yardstick
+{% for vnf_num in range(num_vnfs|int) %}
+      vnf__{{ vnf_num }}: vnf_{{ vnf_num }}.yardstick
+{% endfor %}
+    options:
+      framesize:
+        uplink: {{ flow.pkt_size.uplink | to_yaml }}
+        downlink: {{ flow.pkt_size.downlink | to_yaml }}
+      flow:
+        src_ip:
+{% for vnf_num in range(num_vnfs|int) %}
+          - {'tg__0': 'xe{{ vnf_num }}'}
+{% endfor %}
+        dst_ip:
+{% for vnf_num in range(num_vnfs|int) %}
+          - {'tg__1': 'xe{{ vnf_num }}'}
+{% endfor %}
+        count: {{ flow.count }}
+      traffic_type: {{ flow.traffic_type }}
+      rfc2544:
+        allowed_drop_rate: {{ flow.rfc2544.allowed_drop_rate }}
+        correlated_traffic: true
+      vnf__0:
+        rules: acl_1rule.yaml
+        vnf_config: {lb_config: '{{flow.vnf_config.lb_config}}', lb_count: {{flow.vnf_config.lb_count}} , worker_config: '{{flow.vnf_config.worker_config}}', worker_threads: {{flow.vnf_config.worker_threads}}}
+    ixia_profile: ../../traffic_profiles/ixia/ixia_ipv4_profile_{{ num_vnfs * 2 }}_port.ixncfg
+
+    runner:
+      type: Iteration
+      iterations: 10
+      interval: 35
+contexts:
+   - name: yardstick
+     type: Node
+     file: /etc/yardstick/nodes/ixia_correlated_{{num_vnfs}}.yaml
+   - type: Node
+     file: /etc/yardstick/nodes/pod_bm_vnf_{{num_vnfs}}.yaml
+     name: yardstick
index fda6671..aa5fdd3 100644 (file)
@@ -45,7 +45,7 @@ VM_TEMPLATE = """
   <vcpu cpuset='{cpuset}'>{vcpu}</vcpu>
  {cputune}
   <os>
-    <type arch="x86_64" machine="pc-i440fx-xenial">hvm</type>
+    <type arch="x86_64" machine="{machine}">hvm</type>
     <boot dev="hd" />
   </os>
   <features>
@@ -306,6 +306,7 @@ class Libvirt(object):
         cpuset = Libvirt.pin_vcpu_for_perf(connection, hw_socket)
 
         cputune = extra_spec.get('cputune', '')
+        machine = extra_spec.get('machine_type', 'pc-i440fx-xenial')
         mac = StandaloneContextHelper.get_mac_address(0x00)
         image = cls.create_snapshot_qemu(connection, index,
                                          flavor.get("images", None))
@@ -316,7 +317,8 @@ class Libvirt(object):
             memory=memory, vcpu=vcpu, cpu=cpu,
             numa_cpus=numa_cpus,
             socket=socket, threads=threads,
-            vm_image=image, cpuset=cpuset, cputune=cputune)
+            vm_image=image, cpuset=cpuset,
+            machine=machine, cputune=cputune)
 
         # Add CD-ROM device
         vm_xml = Libvirt.add_cdrom(cdrom_img, vm_xml)
index 42a2754..3a310f1 100644 (file)
@@ -74,6 +74,11 @@ class OvsDpdkContext(base.Context):
         self.wait_for_vswitchd = 10
         super(OvsDpdkContext, self).__init__()
 
+    def get_dpdk_socket_mem_size(self, socket_id):
+        """Get the size of OvS DPDK socket memory (Mb)"""
+        ram = self.ovs_properties.get("ram", {})
+        return ram.get('socket_%d' % (socket_id), 2048)
+
     def init(self, attrs):
         """initializes itself from the supplied arguments"""
         super(OvsDpdkContext, self).init(attrs)
@@ -134,9 +139,6 @@ class OvsDpdkContext(base.Context):
         if pmd_cpu_mask:
             pmd_mask = pmd_cpu_mask
 
-        socket0 = self.ovs_properties.get("ram", {}).get("socket_0", "2048")
-        socket1 = self.ovs_properties.get("ram", {}).get("socket_1", "2048")
-
         ovs_other_config = "ovs-vsctl {0}set Open_vSwitch . other_config:{1}"
         detach_cmd = "ovs-vswitchd unix:{0}{1} --pidfile --detach --log-file={2}"
 
@@ -154,7 +156,9 @@ class OvsDpdkContext(base.Context):
             ("ovsdb-server --remote=punix:/{0}/{1} --remote=ptcp:6640"
              " --pidfile --detach").format(vpath, ovs_sock_path),
             ovs_other_config.format("--no-wait ", "dpdk-init=true"),
-            ovs_other_config.format("--no-wait ", "dpdk-socket-mem='%s,%s'" % (socket0, socket1)),
+            ovs_other_config.format("--no-wait ", "dpdk-socket-mem='%d,%d'" % (
+                self.get_dpdk_socket_mem_size(0),
+                self.get_dpdk_socket_mem_size(1))),
             lcore_mask,
             detach_cmd.format(vpath, ovs_sock_path, log_path),
             ovs_other_config.format("", "pmd-cpu-mask=%s" % pmd_mask),
@@ -399,7 +403,9 @@ class OvsDpdkContext(base.Context):
         self.configure_nics_for_ovs_dpdk()
 
         hp_total_mb = int(self.vm_flavor.get('ram', '4096')) * len(self.servers)
-        common_utils.setup_hugepages(self.connection, hp_total_mb * 1024)
+        common_utils.setup_hugepages(self.connection, (hp_total_mb + \
+                                     self.get_dpdk_socket_mem_size(0) + \
+                                     self.get_dpdk_socket_mem_size(1)) * 1024)
 
         self._check_hugepages()
 
index 1996024..a484a49 100644 (file)
@@ -1,7 +1,7 @@
-#############################################################################
-# Copyright (c) 2017 Rajesh Kudaka
+##############################################################################
+# Copyright (c) 2017 Rajesh Kudaka <4k.rajesh@gmail.com>
+# Copyright (c) 2018 Intel Corporation.
 #
-# Author: Rajesh Kudaka 4k.rajesh@gmail.com
 # 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
 
 """ Handler for yardstick command 'report' """
 
-from __future__ import print_function
-
-from __future__ import absolute_import
-
 import ast
 import re
 import uuid
 
+import jinja2
 from api.utils import influx
-
-from django.conf import settings
-from django.template import Context
-from django.template import Template
-
 from oslo_utils import encodeutils
 from oslo_utils import uuidutils
 from yardstick.common import constants as consts
-from yardstick.common.html_template import template
 from yardstick.common.utils import cliargs
 
-settings.configure()
+
+class JSTree(object):
+    """Data structure to parse data for use with the JS library jsTree"""
+    def __init__(self):
+        self._created_nodes = ['#']
+        self.jstree_data = []
+
+    def _create_node(self, _id):
+        """Helper method for format_for_jstree to create each node.
+
+        Creates the node (and any required parents) and keeps track
+        of the created nodes.
+
+        :param _id: (string) id of the node to be created
+        :return: None
+        """
+        components = _id.split(".")
+
+        if len(components) == 1:
+            text = components[0]
+            parent_id = "#"
+        else:
+            text = components[-1]
+            parent_id = ".".join(components[:-1])
+            # make sure the parent has been created
+            if not parent_id in self._created_nodes:
+                self._create_node(parent_id)
+
+        self.jstree_data.append({"id": _id, "text": text, "parent": parent_id})
+        self._created_nodes.append(_id)
+
+    def format_for_jstree(self, data):
+        """Format the data into the required format for jsTree.
+
+        The data format expected is a list of key-value pairs which represent
+        the data and name for each metric e.g.:
+
+            [{'data': [0, ], 'name': 'tg__0.DropPackets'},
+             {'data': [548, ], 'name': 'tg__0.LatencyAvg.5'},]
+
+        This data is converted into the format required for jsTree to group and
+        display the metrics in a hierarchial fashion, including creating a
+        number of parent nodes e.g.::
+
+            [{"id": "tg__0", "text": "tg__0", "parent": "#"},
+             {"id": "tg__0.DropPackets", "text": "DropPackets", "parent": "tg__0"},
+             {"id": "tg__0.LatencyAvg", "text": "LatencyAvg", "parent": "tg__0"},
+             {"id": "tg__0.LatencyAvg.5", "text": "5", "parent": "tg__0.LatencyAvg"},]
+
+        :param data: (list) data to be converted
+        :return: list
+        """
+        self._created_nodes = ['#']
+        self.jstree_data = []
+
+        for item in data:
+            self._create_node(item["name"])
+
+        return self.jstree_data
 
 
 class Report(object):
@@ -64,7 +113,7 @@ class Report(object):
         if query_exec:
             return query_exec
         else:
-            raise KeyError("Task ID or Test case not found..")
+            raise KeyError("Test case not found.")
 
     def _get_tasks(self):
         task_cmd = "select * from \"%s\" where task_id= '%s'"
@@ -73,7 +122,7 @@ class Report(object):
         if query_exec:
             return query_exec
         else:
-            raise KeyError("Task ID or Test case not found..")
+            raise KeyError("Task ID or Test case not found.")
 
     @cliargs("task_id", type=str, help=" task id", nargs=1)
     @cliargs("yaml_name", type=str, help=" Yaml file Name", nargs=1)
@@ -117,12 +166,22 @@ class Report(object):
             series['data'] = values
             temp_series.append(series)
 
-        Template_html = Template(template)
-        Context_html = Context({"series": temp_series,
-                                "Timestamp": self.Timestamp,
-                                "task_id": self.task_id,
-                                "table": table_vals})
+        template_dir = consts.YARDSTICK_ROOT_PATH + "yardstick/common"
+        template_environment = jinja2.Environment(
+            autoescape=False,
+            loader=jinja2.FileSystemLoader(template_dir),
+            trim_blocks=False)
+
+        context = {
+            "series": temp_series,
+            "Timestamps": self.Timestamp,
+            "task_id": self.task_id,
+            "table": table_vals,
+        }
+
+        template_html = template_environment.get_template("report.html.j2")
+
         with open(consts.DEFAULT_HTML_FILE, "w") as file_open:
-            file_open.write(Template_html.render(Context_html))
+            file_open.write(template_html.render(context))
 
         print("Report generated. View /tmp/yardstick.htm")
index e17c766..c15dd82 100644 (file)
@@ -8,130 +8,6 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 #############################################################################
 
-template = """
-<html>
-<body>
-<head>
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7\
-/css/bootstrap.min.css">
-<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1\
-/jquery.min.js"></script>
-<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7\
-/js/bootstrap.min.js"></script>
-<script src="https://code.highcharts.com/highcharts.js"></script>
-<script src="jquery.min.js"></script>
-<script src="highcharts.js"></script>
-</head>
-<style>
-
-table{
-  overflow-y: scroll;
-  height: 360px;
-  display: block;
-  }
-
- header,h3{
-    font-family:Frutiger;
-    clear: left;
-    text-align: center;
-}
-</style>
-<header class="jumbotron text-center">
-  <h1>Yardstick User Interface</h1>
-  <h4>Report of {{task_id}} Generated</h4>
-</header>
-
-<div class="container">
-  <div class="row">
-    <div class="col-md-4">
-        <div class="table-responsive" >
-        <table  class="table table-hover" > </table>
-        </div>
-    </div>
-    <div class="col-md-8" >
-    <div id="container" ></div>
-   </div>
-  </div>
-</div>
-<script>
-  var arr, tab, th, tr, td, tn, row, col, thead, tbody;
-  arr={{table|safe}}
-  tab = document.getElementsByTagName('table')[0];
-  thead=document.createElement('thead');
-  tr = document.createElement('tr');
-  for(row=0;row<Object.keys(arr).length;row++)
-  {
-      th = document.createElement('th');
-      tn = document.createTextNode(Object.keys(arr).sort()[row]);
-      th.appendChild(tn);
-      tr.appendChild(th);
-          thead.appendChild(tr);
-  }
-  tab.appendChild(thead);
-  tbody=document.createElement('tbody');
-
-  for (col = 0; col < arr[Object.keys(arr)[0]].length; col++){
-  tr = document.createElement('tr');
-  for(row=0;row<Object.keys(arr).length;row++)
-  {
-      td = document.createElement('td');
-      tn = document.createTextNode(arr[Object.keys(arr).sort()[row]][col]);
-      td.appendChild(tn);
-      tr.appendChild(td);
-  }
-    tbody.appendChild(tr);
-        }
-tab.appendChild(tbody);
-
-</script>
-
-<script language="JavaScript">
-
-$(function() {
-  $('#container').highcharts({
-    title: {
-      text: 'Yardstick test results',
-      x: -20 //center
-    },
-    subtitle: {
-      text: 'Report of {{task_id}} Task Generated',
-      x: -20
-    },
-    xAxis: {
-      title: {
-        text: 'Timestamp'
-      },
-      categories:{{Timestamp|safe}}
-    },
-    yAxis: {
-
-      plotLines: [{
-        value: 0,
-        width: 1,
-        color: '#808080'
-      }]
-    },
-    tooltip: {
-      valueSuffix: ''
-    },
-    legend: {
-      layout: 'vertical',
-      align: 'right',
-      verticalAlign: 'middle',
-      borderWidth: 0
-    },
-    series: {{series|safe}}
-  });
-});
-
-</script>
-
-
-</body>
-</html>"""
-
 report_template = """
 <html>
     <head>
diff --git a/yardstick/common/nsb_report.css b/yardstick/common/nsb_report.css
new file mode 100644 (file)
index 0000000..0c47791
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Rajesh Kudaka <4k.rajesh@gmail.com>
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Apache License, Version 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ ******************************************************************************/
+
+body {
+    font-size: 16pt;
+}
+
+table {
+    overflow-y: scroll;
+    height: 360px;
+    display: block;
+}
+
+header {
+    font-family: Frutiger;
+    clear: left;
+    text-align: center;
+}
+
+.control-pane {
+    font-size: 10pt;
+}
diff --git a/yardstick/common/nsb_report.html.j2 b/yardstick/common/nsb_report.html.j2
new file mode 100644 (file)
index 0000000..f1b4ae1
--- /dev/null
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<html>
+
+<!--
+ Copyright (c) 2017 Rajesh Kudaka <4k.rajesh@gmail.com>
+ Copyright (c) 2018 Intel Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Apache License, Version 2.0
+ which accompanies this distribution, and is available at
+ http://www.apache.org/licenses/LICENSE-2.0
+-->
+
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
+        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.5/themes/default/style.min.css">
+        <link rel="stylesheet" href="{{template_dir}}/nsb_report.css">
+        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
+        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
+        <script src="https://code.highcharts.com/highcharts.js"></script>
+    </head>
+
+    <body>
+        <div class="container" style="width:80%">
+            <div class="row">
+                <header class="jumbotron">
+                    <h1>Yardstick User Interface</h1>
+                    <h4>Report of {{task_id}} Generated</h4>
+                </header>
+            </div>
+            <div class="row" style="height:500px">
+                <div class="col-md-2 control-pane">
+                    <div id="data_selector"></div>
+                </div>
+                <div class="col-md-10 data-pane">
+                    <div id="graph"></div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-md-12 table-responsive">
+                    <table class="table table-hover"></table>
+                </div>
+            </div>
+        </div>
+
+        <script>
+            var arr, tab, tr, td, tbody, keys, key, curr_data;
+            arr = {{table|safe}};
+
+            tab = document.getElementsByTagName('table')[0];
+            tbody = document.createElement('tbody');
+            keys = Object.keys(arr);
+            // for each metric
+            for (var i = 0; i < keys.length; i++) {
+                tr = document.createElement('tr');
+                td = document.createElement('td');
+                key = keys[i];
+                td.append(key);
+                tr.append(td);
+                curr_data = arr[key];
+                // add each piece of data as its own column
+                for (var j = 0; j < curr_data.length; j++) {
+                    td = document.createElement('td');
+                    td.append(curr_data[j]);
+                    tr.append(td);
+                }
+                tbody.append(tr);
+            }
+            tab.appendChild(tbody);
+
+            $(function() {
+                $('#data_selector').jstree({
+                    plugins: ['checkbox'],
+                    checkbox: {
+                        three_state: false,
+                        whole_node: true,
+                        tie_selection: false,
+                    },
+                    core: {
+                        themes: {
+                            icons: false,
+                            stripes: true,
+                        },
+                        data: {{jstree_nodes|safe}},
+                    },
+                });
+
+                $('#data_selector').on('check_node.jstree uncheck_node.jstree', function(e, data) {
+                    var selected_leaves = [];
+                    for (var i = 0; i < data.selected.length; i++) {
+                        var node = data.instance.get_node(data.selected[i]);
+                        if (node.children.length == 0) {
+                            var point = {name: node.id, data: arr[node.id]};
+                            selected_leaves.push(point);
+                        }
+                    }
+
+                    $('#graph').highcharts({
+                        title: {
+                            text: 'Yardstick Graphs',
+                            x: -20, //center
+                        },
+                        chart: {
+                            marginLeft: 400,
+                            zoomType: 'x',
+                            type: 'spline',
+                        },
+                        xAxis: {
+                            crosshair: {
+                                width: 1,
+                                color: 'black',
+                            },
+                            title: {
+                                text: 'Timestamp',
+                            },
+                            categories: {{Timestamps|safe}},
+                        },
+                        yAxis: {
+                            crosshair: {
+                                width: 1,
+                                color: 'black',
+                            },
+                            plotLines: [{
+                                value: 0,
+                                width: 1,
+                                color: '#808080',
+                            }],
+                        },
+                        plotOptions: {
+                            series: {
+                                showCheckbox: false,
+                                visible: false,
+                            },
+                        },
+                        tooltip: {
+                            valueSuffix: '',
+                        },
+                        legend: {
+                            enabled: true,
+                        },
+                        series: selected_leaves,
+                    });
+
+                    var chart = $('#graph').highcharts();
+                    for (var i = 0; i < chart.series.length; i++) {
+                        var series = chart.series[i];
+                        if (series.visible) {
+                            series.hide();
+                        } else {
+                            series.show();
+                        }
+                    }
+                });
+            });
+        </script>
+    </body>
+</html>
diff --git a/yardstick/common/report.html.j2 b/yardstick/common/report.html.j2
new file mode 100644 (file)
index 0000000..ab76510
--- /dev/null
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<html>
+
+<!--
+ Copyright (c) 2017 Rajesh Kudaka <4k.rajesh@gmail.com>
+ Copyright (c) 2018 Intel Corporation.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Apache License, Version 2.0
+ which accompanies this distribution, and is available at
+ http://www.apache.org/licenses/LICENSE-2.0
+-->
+
+    <head>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
+        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
+        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
+        <script src="https://code.highcharts.com/highcharts.js"></script>
+
+        <style>
+            table {
+                overflow-y: scroll;
+                height: 360px;
+                display: block;
+            }
+            header {
+                font-family: Frutiger;
+                clear: left;
+                text-align: center;
+            }
+        </style>
+    </head>
+
+    <body>
+        <header class="jumbotron text-center">
+            <h1>Yardstick User Interface</h1>
+            <h4>Report of {{task_id}} Generated</h4>
+        </header>
+
+        <div class="container">
+            <div class="row">
+                <div class="col-md-4">
+                    <div class="table-responsive">
+                        <table class="table table-hover"></table>
+                    </div>
+                </div>
+                <div class="col-md-8">
+                    <div id="container"></div>
+                </div>
+            </div>
+        </div>
+
+        <script>
+            var arr, tab, th, tr, td, tn, row, col, thead, tbody;
+            arr = {{table|safe}};
+            tab = document.getElementsByTagName('table')[0];
+
+            thead = document.createElement('thead');
+            tr = document.createElement('tr');
+            for (col = 0; col < Object.keys(arr).length; col++) {
+                th = document.createElement('th');
+                tn = document.createTextNode(Object.keys(arr).sort()[col]);
+                th.appendChild(tn);
+                tr.appendChild(th);
+                thead.appendChild(tr);
+            }
+            tab.appendChild(thead);
+
+            tbody = document.createElement('tbody');
+            for (row = 0; row < arr[Object.keys(arr)[0]].length; row++) {
+                tr = document.createElement('tr');
+                for (col = 0; col < Object.keys(arr).length; col++) {
+                    td = document.createElement('td');
+                    tn = document.createTextNode(arr[Object.keys(arr).sort()[col]][row]);
+                    td.appendChild(tn);
+                    tr.appendChild(td);
+                }
+                tbody.appendChild(tr);
+            }
+            tab.appendChild(tbody);
+
+            $(function() {
+                $('#container').highcharts({
+                    title: {
+                        text: 'Yardstick test results',
+                        x: -20, //center
+                    },
+                    subtitle: {
+                        text: 'Report of {{task_id}} Task Generated',
+                        x: -20,
+                    },
+                    xAxis: {
+                        title: {
+                            text: 'Timestamp',
+                        },
+                        categories: {{Timestamps|safe}},
+                    },
+                    yAxis: {
+                        plotLines: [{
+                            value: 0,
+                            width: 1,
+                            color: '#808080',
+                        }],
+                    },
+                    tooltip: {
+                        valueSuffix: '',
+                    },
+                    legend: {
+                        layout: 'vertical',
+                        align: 'right',
+                        verticalAlign: 'middle',
+                        borderWidth: 0,
+                    },
+                    series: {{series|safe}},
+                });
+            });
+        </script>
+    </body>
+</html>
index 2052479..51313ef 100644 (file)
@@ -30,6 +30,7 @@ import subprocess
 import sys
 import time
 import threading
+import math
 
 import six
 from flask import jsonify
@@ -505,7 +506,7 @@ def setup_hugepages(ssh_client, size_kb):
     NR_HUGEPAGES_PATH = '/proc/sys/vm/nr_hugepages'
     meminfo = read_meminfo(ssh_client)
     hp_size_kb = int(meminfo['Hugepagesize'])
-    hp_number = int(abs(size_kb / hp_size_kb))
+    hp_number = int(math.ceil(size_kb / float(hp_size_kb)))
     ssh_client.execute(
         'echo %s | sudo tee %s' % (hp_number, NR_HUGEPAGES_PATH))
     hp = six.BytesIO()
index f924cf4..402bf74 100644 (file)
@@ -168,8 +168,8 @@ class ProxBinSearchProfile(ProxProfile):
 
                 samples = result.get_samples(pkt_size, successful_pkt_loss, port_samples)
 
-                if theor_max_thruput < samples["TxThroughput"]:
-                    theor_max_thruput = samples['TxThroughput']
+                if theor_max_thruput < samples["RequestedTxThroughput"]:
+                    theor_max_thruput = samples['RequestedTxThroughput']
                 samples['theor_max_throughput'] = theor_max_thruput
 
                 samples["rx_total"] = int(result.rx_total)
index 8d721c0..e9d8362 100644 (file)
@@ -601,6 +601,99 @@ class ProxSocketHelper(object):
         LOG.debug("Multi port packet ..OK.. %s", tot_result)
         return True, tot_result
 
+    @staticmethod
+    def multi_port_stats_tuple(stats, ports):
+        """
+        Create a statistics tuple from port stats.
+
+        Returns a dict with contains the port stats indexed by port name
+
+        :param stats: (List) - List of List of port stats in pps
+        :param ports (Iterator) - to List of Ports
+
+        :return: (Dict) of port stats indexed by port_name
+        """
+
+        samples = {}
+        port_names = {}
+        try:
+            port_names = {port_num: port_name for port_name, port_num in ports}
+        except (TypeError, IndexError, KeyError):
+            LOG.critical("Ports are not initialized or number of port is ZERO ... CRITICAL ERROR")
+            return {}
+
+        try:
+            for stat in stats:
+                port_num = stat[0]
+                samples[port_names[port_num]] = {
+                    "in_packets": stat[1],
+                    "out_packets": stat[2]}
+        except (TypeError, IndexError, KeyError):
+            LOG.error("Ports data and samples data is incompatable ....")
+            return {}
+
+        return samples
+
+    @staticmethod
+    def multi_port_stats_diff(prev_stats, new_stats, hz):
+        """
+        Create a statistics tuple from difference between prev port stats
+        and current port stats. And store results in pps.
+
+        :param prev_stats: (List) - Previous List of port statistics
+        :param new_stats: (List) - Current List of port statistics
+        :param hz (float) - speed of system in Hz
+
+        :return: sample (List) - Difference of prev_port_stats and
+                new_port_stats  in pps
+        """
+
+        RX_TOTAL_INDEX = 1
+        TX_TOTAL_INDEX = 2
+        TSC_INDEX = 5
+
+        stats = []
+
+        if len(prev_stats) is not len(new_stats):
+            for port_index, stat in enumerate(new_stats):
+                stats.append([port_index, float(0), float(0), 0, 0, 0])
+            return stats
+
+        try:
+            for port_index, stat in enumerate(new_stats):
+                if stat[RX_TOTAL_INDEX] > prev_stats[port_index][RX_TOTAL_INDEX]:
+                    rx_total = stat[RX_TOTAL_INDEX] - \
+                               prev_stats[port_index][RX_TOTAL_INDEX]
+                else:
+                    rx_total = stat[RX_TOTAL_INDEX]
+
+                if stat[TX_TOTAL_INDEX] > prev_stats[port_index][TX_TOTAL_INDEX]:
+                    tx_total = stat[TX_TOTAL_INDEX] - prev_stats[port_index][TX_TOTAL_INDEX]
+                else:
+                    tx_total = stat[TX_TOTAL_INDEX]
+
+                if stat[TSC_INDEX] > prev_stats[port_index][TSC_INDEX]:
+                    tsc = stat[TSC_INDEX] - prev_stats[port_index][TSC_INDEX]
+                else:
+                    tsc = stat[TSC_INDEX]
+
+                if tsc is 0:
+                    rx_total = tx_total = float(0)
+                else:
+                    if hz is 0:
+                        LOG.error("HZ is ZERO ..")
+                        rx_total = tx_total = float(0)
+                    else:
+                        rx_total = float(rx_total * hz / tsc)
+                        tx_total = float(tx_total * hz / tsc)
+
+                stats.append([port_index, rx_total, tx_total, 0, 0, tsc])
+        except (TypeError, IndexError, KeyError):
+            stats = []
+            LOG.info("Current Port Stats incompatable to previous Port stats .. Discarded")
+
+        return stats
+
     def port_stats(self, ports):
         """get counter values from a specific port"""
         tot_result = [0] * 12
@@ -968,6 +1061,8 @@ class ProxResourceHelper(ClientResourceHelper):
         self.step_delta = 1
         self.step_time = 0.5
         self._test_type = None
+        self.prev_multi_port = []
+        self.prev_hz = 0
 
     @property
     def sut(self):
@@ -1006,11 +1101,40 @@ class ProxResourceHelper(ClientResourceHelper):
     def collect_collectd_kpi(self):
         return self._collect_resource_kpi()
 
+    def collect_live_stats(self):
+        ports = []
+        for _, port_num in self.vnfd_helper.ports_iter():
+            ports.append(port_num)
+
+        ok, curr_port_stats = self.sut.multi_port_stats(ports)
+        if not ok:
+            return False, {}
+
+        hz = self.sut.hz()
+        if hz is 0:
+            hz = self.prev_hz
+        else:
+            self.prev_hz = hz
+
+        new_all_port_stats = \
+            self.sut.multi_port_stats_diff(self.prev_multi_port, curr_port_stats, hz)
+
+        self.prev_multi_port = curr_port_stats
+
+        live_stats = self.sut.multi_port_stats_tuple(new_all_port_stats,
+                                                     self.vnfd_helper.ports_iter())
+        return True, live_stats
+
     def collect_kpi(self):
         result = super(ProxResourceHelper, self).collect_kpi()
         # add in collectd kpis manually
         if result:
             result['collect_stats'] = self._collect_resource_kpi()
+
+        ok, live_stats = self.collect_live_stats()
+        if ok:
+            result.update({'live_stats': live_stats})
+
         return result
 
     def terminate(self):
index d880b41..e76a3ca 100644 (file)
@@ -55,7 +55,7 @@ class ModelLibvirtTestCase(unittest.TestCase):
         numa_cpus=0 - 10,
         socket=1, threads=1,
         vm_image="/var/lib/libvirt/images/yardstick-nsb-image.img",
-        cpuset=2 - 10, cputune='')
+        cpuset=2 - 10, cputune='', machine='pc')
 
     def setUp(self):
         self.pci_address_str = '0001:04:03.2'
@@ -352,7 +352,8 @@ class ModelLibvirtTestCase(unittest.TestCase):
         xml_ref = model.VM_TEMPLATE.format(vm_name='vm_name',
             random_uuid=_uuid, mac_addr=mac, memory='1024', vcpu='8', cpu='4',
             numa_cpus='0-7', socket='3', threads='2',
-            vm_image='qemu_image', cpuset='4,5', cputune='cool')
+            vm_image='qemu_image', cpuset='4,5', cputune='cool',
+            machine='pc-i440fx-xenial')
         xml_ref = model.Libvirt.add_cdrom(cdrom_img, xml_ref)
         self.assertEqual(xml_out, xml_ref)
         mock_get_mac_address.assert_called_once_with(0x00)
index 190e83d..b5051e9 100644 (file)
@@ -430,7 +430,8 @@ class OvsDpdkContextTestCase(unittest.TestCase):
 
         self.assertEqual([vnf_instance_2],
                          self.ovs_dpdk.setup_ovs_dpdk_context())
-        mock_setup_hugepages.assert_called_once_with(self.ovs_dpdk.connection, 1024 * 1024)
+        mock_setup_hugepages.assert_called_once_with(self.ovs_dpdk.connection,
+            (1024 + 4096) * 1024) # ram + dpdk_socket0_mem + dpdk_socket1_mem
         mock__check_hugepages.assert_called_once()
         mock_create_vm.assert_called_once_with(
             self.ovs_dpdk.connection, '/tmp/vm_ovs_0.xml')
index 524302f..3e80dcc 100644 (file)
@@ -1,5 +1,6 @@
 ##############################################################################
 # Copyright (c) 2017 Rajesh Kudaka.
+# Copyright (c) 2018 Intel Corporation.
 #
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Apache License, Version 2.0
@@ -7,30 +8,93 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-# Unittest for yardstick.benchmark.core.report
-
-from __future__ import print_function
-
-from __future__ import absolute_import
-
+import mock
 import unittest
 import uuid
 
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
+from api.utils import influx
 from yardstick.benchmark.core import report
 from yardstick.cmd.commands import change_osloobj_to_paras
 
-FAKE_YAML_NAME = 'fake_name'
-FAKE_TASK_ID = str(uuid.uuid4())
-FAKE_DB_FIELDKEYS = [{'fieldKey': 'fake_key'}]
-FAKE_TIME = '0000-00-00T00:00:00.000000Z'
-FAKE_DB_TASK = [{'fake_key': 0.000, 'time': FAKE_TIME}]
-FAKE_TIMESTAMP = ['fake_time']
-DUMMY_TASK_ID = 'aaaaaa-aaaaaaaa-aaaaaaaaaa-aaaaaa'
+GOOD_YAML_NAME = 'fake_name'
+GOOD_TASK_ID = str(uuid.uuid4())
+GOOD_DB_FIELDKEYS = [{'fieldKey': 'fake_key'}]
+GOOD_DB_TASK = [{
+        'fake_key': 0.000,
+        'time': '0000-00-00T00:00:00.000000Z',
+        }]
+GOOD_TIMESTAMP = ['00:00:00.000000']
+BAD_YAML_NAME = 'F@KE_NAME'
+BAD_TASK_ID = 'aaaaaa-aaaaaaaa-aaaaaaaaaa-aaaaaa'
+
+
+class JSTreeTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.jstree = report.JSTree()
+
+    def test__create_node(self):
+        _id = "tg__0.DropPackets"
+
+        expected_data = [
+            {"id": "tg__0", "text": "tg__0", "parent": "#"},
+            {"id": "tg__0.DropPackets", "text": "DropPackets", "parent": "tg__0"}
+        ]
+        self.jstree._create_node(_id)
+
+        self.assertEqual(self.jstree._created_nodes, ['#', 'tg__0', 'tg__0.DropPackets'])
+        self.assertEqual(self.jstree.jstree_data, expected_data)
+
+    def test_format_for_jstree(self):
+        data = [
+            {'data': [0, ], 'name': 'tg__0.DropPackets'},
+            {'data': [548, ], 'name': 'tg__0.LatencyAvg.5'},
+            {'data': [1172, ], 'name': 'tg__0.LatencyAvg.6'},
+            {'data': [1001, ], 'name': 'tg__0.LatencyMax.5'},
+            {'data': [1468, ], 'name': 'tg__0.LatencyMax.6'},
+            {'data': [18.11, ], 'name': 'tg__0.RxThroughput'},
+            {'data': [18.11, ], 'name': 'tg__0.TxThroughput'},
+            {'data': [0, ], 'name': 'tg__1.DropPackets'},
+            {'data': [548, ], 'name': 'tg__1.LatencyAvg.5'},
+            {'data': [1172, ], 'name': 'tg__1.LatencyAvg.6'},
+            {'data': [1001, ], 'name': 'tg__1.LatencyMax.5'},
+            {'data': [1468, ], 'name': 'tg__1.LatencyMax.6'},
+            {'data': [18.1132084505, ], 'name': 'tg__1.RxThroughput'},
+            {'data': [18.1157260383, ], 'name': 'tg__1.TxThroughput'},
+            {'data': [9057888, ], 'name': 'vnf__0.curr_packets_in'},
+            {'data': [0, ], 'name': 'vnf__0.packets_dropped'},
+            {'data': [617825443, ], 'name': 'vnf__0.packets_fwd'},
+        ]
+
+        expected_output = [
+            {"id": "tg__0", "text": "tg__0", "parent": "#"},
+                {"id": "tg__0.DropPackets", "text": "DropPackets", "parent": "tg__0"},
+                {"id": "tg__0.LatencyAvg", "text": "LatencyAvg", "parent": "tg__0"},
+                    {"id": "tg__0.LatencyAvg.5", "text": "5", "parent": "tg__0.LatencyAvg"},
+                    {"id": "tg__0.LatencyAvg.6", "text": "6", "parent": "tg__0.LatencyAvg"},
+                {"id": "tg__0.LatencyMax", "text": "LatencyMax", "parent": "tg__0"},
+                    {"id": "tg__0.LatencyMax.5", "text": "5", "parent": "tg__0.LatencyMax"},
+                    {"id": "tg__0.LatencyMax.6", "text": "6", "parent": "tg__0.LatencyMax"},
+                {"id": "tg__0.RxThroughput", "text": "RxThroughput", "parent": "tg__0"},
+                {"id": "tg__0.TxThroughput", "text": "TxThroughput", "parent": "tg__0"},
+            {"id": "tg__1", "text": "tg__1", "parent": "#"},
+                {"id": "tg__1.DropPackets", "text": "DropPackets", "parent": "tg__1"},
+                {"id": "tg__1.LatencyAvg", "text": "LatencyAvg", "parent": "tg__1"},
+                    {"id": "tg__1.LatencyAvg.5", "text": "5", "parent": "tg__1.LatencyAvg"},
+                    {"id": "tg__1.LatencyAvg.6", "text": "6", "parent": "tg__1.LatencyAvg"},
+                {"id": "tg__1.LatencyMax", "text": "LatencyMax", "parent": "tg__1"},
+                    {"id": "tg__1.LatencyMax.5", "text": "5", "parent": "tg__1.LatencyMax"},
+                    {"id": "tg__1.LatencyMax.6", "text": "6", "parent": "tg__1.LatencyMax"},
+                {"id": "tg__1.RxThroughput", "text": "RxThroughput", "parent": "tg__1"},
+                {"id": "tg__1.TxThroughput", "text": "TxThroughput", "parent": "tg__1"},
+            {"id": "vnf__0", "text": "vnf__0", "parent": "#"},
+                {"id": "vnf__0.curr_packets_in", "text": "curr_packets_in", "parent": "vnf__0"},
+                {"id": "vnf__0.packets_dropped", "text": "packets_dropped", "parent": "vnf__0"},
+                {"id": "vnf__0.packets_fwd", "text": "packets_fwd", "parent": "vnf__0"},
+        ]
+
+        result = self.jstree.format_for_jstree(data)
+        self.assertEqual(expected_output, result)
 
 
 class ReportTestCase(unittest.TestCase):
@@ -38,37 +102,69 @@ class ReportTestCase(unittest.TestCase):
     def setUp(self):
         super(ReportTestCase, self).setUp()
         self.param = change_osloobj_to_paras({})
-        self.param.yaml_name = [FAKE_YAML_NAME]
-        self.param.task_id = [FAKE_TASK_ID]
+        self.param.yaml_name = [GOOD_YAML_NAME]
+        self.param.task_id = [GOOD_TASK_ID]
         self.rep = report.Report()
 
+    def test___init__(self):
+        self.assertEqual([], self.rep.Timestamp)
+        self.assertEqual("", self.rep.yaml_name)
+        self.assertEqual("", self.rep.task_id)
+
+    def test__validate(self):
+        self.rep._validate(GOOD_YAML_NAME, GOOD_TASK_ID)
+        self.assertEqual(GOOD_YAML_NAME, self.rep.yaml_name)
+        self.assertEqual(GOOD_TASK_ID, str(self.rep.task_id))
+
+    def test__validate_invalid_yaml_name(self):
+        with self.assertRaisesRegexp(ValueError, "yaml*"):
+            self.rep._validate(BAD_YAML_NAME, GOOD_TASK_ID)
+
+    def test__validate_invalid_task_id(self):
+        with self.assertRaisesRegexp(ValueError, "task*"):
+            self.rep._validate(GOOD_YAML_NAME, BAD_TASK_ID)
+
+    @mock.patch.object(influx, 'query')
+    def test__get_fieldkeys(self, mock_query):
+        mock_query.return_value = GOOD_DB_FIELDKEYS
+        self.rep.yaml_name = GOOD_YAML_NAME
+        self.rep.task_id = GOOD_TASK_ID
+        self.assertEqual(GOOD_DB_FIELDKEYS, self.rep._get_fieldkeys())
+
+    @mock.patch.object(influx, 'query')
+    def test__get_fieldkeys_nodbclient(self, mock_query):
+        mock_query.side_effect = RuntimeError
+        self.assertRaises(RuntimeError, self.rep._get_fieldkeys)
+
+    @mock.patch.object(influx, 'query')
+    def test__get_fieldkeys_testcase_not_found(self, mock_query):
+        mock_query.return_value = []
+        self.rep.yaml_name = GOOD_YAML_NAME
+        self.rep.task_id = GOOD_TASK_ID
+        self.assertRaisesRegexp(KeyError, "Test case", self.rep._get_fieldkeys)
+
+    @mock.patch.object(influx, 'query')
+    def test__get_tasks(self, mock_query):
+        mock_query.return_value = GOOD_DB_TASK
+        self.rep.yaml_name = GOOD_YAML_NAME
+        self.rep.task_id = GOOD_TASK_ID
+        self.assertEqual(GOOD_DB_TASK, self.rep._get_tasks())
+
+    @mock.patch.object(influx, 'query')
+    def test__get_tasks_task_not_found(self, mock_query):
+        mock_query.return_value = []
+        self.rep.yaml_name = GOOD_YAML_NAME
+        self.rep.task_id = GOOD_TASK_ID
+        self.assertRaisesRegexp(KeyError, "Task ID", self.rep._get_tasks)
+
     @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
+    def test_generate(self, mock_valid, mock_keys, mock_tasks):
+        mock_tasks.return_value = GOOD_DB_TASK
+        mock_keys.return_value = GOOD_DB_FIELDKEYS
         self.rep.generate(self.param)
-        mock_valid.assert_called_once_with(FAKE_YAML_NAME, FAKE_TASK_ID)
+        mock_valid.assert_called_once_with(GOOD_YAML_NAME, GOOD_TASK_ID)
         mock_tasks.assert_called_once_with()
         mock_keys.assert_called_once_with()
-
-    # pylint: disable=deprecated-method
-    def test_invalid_yaml_name(self):
-        self.assertRaisesRegexp(ValueError, "yaml*", self.rep._validate,
-                                'F@KE_NAME', FAKE_TASK_ID)
-
-    # pylint: disable=deprecated-method
-    def test_invalid_task_id(self):
-        self.assertRaisesRegexp(ValueError, "task*", self.rep._validate,
-                                FAKE_YAML_NAME, DUMMY_TASK_ID)
-
-    @mock.patch('api.utils.influx.query')
-    def test_task_not_found(self, mock_query):
-        mock_query.return_value = []
-        self.rep.yaml_name = FAKE_YAML_NAME
-        self.rep.task_id = FAKE_TASK_ID
-        # pylint: disable=deprecated-method
-        self.assertRaisesRegexp(KeyError, "Task ID", self.rep._get_fieldkeys)
-        self.assertRaisesRegexp(KeyError, "Task ID", self.rep._get_tasks)
-        # pylint: enable=deprecated-method
+        self.assertEqual(GOOD_TIMESTAMP, self.rep.Timestamp)
index 4524eb7..f176563 100644 (file)
@@ -21,6 +21,8 @@ from yardstick.network_services.traffic_profile import prox_binsearch
 
 class TestProxBinSearchProfile(unittest.TestCase):
 
+    THEOR_MAX_THROUGHPUT = 0.00012340000000000002
+
     def setUp(self):
         self._mock_log_info = mock.patch.object(prox_binsearch.LOG, 'info')
         self.mock_log_info = self._mock_log_info.start()
@@ -80,7 +82,7 @@ class TestProxBinSearchProfile(unittest.TestCase):
 
         # Result Samples inc theor_max
         result_tuple = {'Actual_throughput': 5e-07,
-                        'theor_max_throughput': 7.5e-07,
+                        'theor_max_throughput': self.THEOR_MAX_THROUGHPUT,
                         'PktSize': 200,
                         'Status': 'Result'}
 
@@ -96,7 +98,7 @@ class TestProxBinSearchProfile(unittest.TestCase):
                                 "PktSize": 200,
                                 "RxThroughput": 7.5e-07,
                                 "Throughput": 7.5e-07,
-                                "TxThroughput": 0.00012340000000000002,
+                                "TxThroughput": self.THEOR_MAX_THROUGHPUT,
                                 "Status": 'Success'}
 
         calls = profile.queue.put(success_result_tuple)
@@ -222,6 +224,7 @@ class TestProxBinSearchProfile(unittest.TestCase):
                 raise RuntimeError(' '.join([str(args), str(runs)]))
             if args[2] > 75.0:
                 return fail_tuple, {}
+
             return success_tuple, {}
 
         tp_config = {
@@ -258,7 +261,7 @@ class TestProxBinSearchProfile(unittest.TestCase):
 
         # Result Samples inc theor_max
         result_tuple = {'Actual_throughput': 5e-07,
-                        'theor_max_throughput': 7.5e-07,
+                        'theor_max_throughput': self.THEOR_MAX_THROUGHPUT,
                         'PktSize': 200,
                         "Status": 'Result'}
 
@@ -274,7 +277,7 @@ class TestProxBinSearchProfile(unittest.TestCase):
                                 "PktSize": 200,
                                 "RxThroughput": 7.5e-07,
                                 "Throughput": 7.5e-07,
-                                "TxThroughput": 0.00012340000000000002,
+                                "TxThroughput": self.THEOR_MAX_THROUGHPUT,
                                 "Status": 'Success'}
 
         calls = profile.queue.put(success_result_tuple)
index 894b16e..6d1d8c6 100644 (file)
@@ -648,6 +648,82 @@ class TestProxSocketHelper(unittest.TestCase):
         self.assertListEqual(result, expected)
         self.assertTrue(ok)
 
+    @mock.patch.object(prox_helpers.LOG, 'error')
+    def test_multi_port_stats_diff(self, *args):
+        mock_socket = mock.MagicMock()
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
+        prox.get_string = mock.MagicMock(return_value=(True, '0,1,2,3,4,5;1,1,2,3,4,5'))
+        _, t1 = prox.multi_port_stats([0, 1])
+
+        prox.get_string = mock.MagicMock(return_value=(True, '0,2,4,6,8,6;1,4,8,16,32,6'))
+        _, t2 = prox.multi_port_stats([0, 1])
+
+        prox.get_string = mock.MagicMock(return_value=(True, '0,1,1,1,1,1;1,1,1,1,1,1'))
+        _, t3 = prox.multi_port_stats([0, 1])
+
+        prox.get_string = mock.MagicMock(return_value=(True, '0,2,2,2,2,2;1,2,2,2,2,2'))
+        _, t4 = prox.multi_port_stats([0, 1])
+
+        expected = [[0, 1.0, 2.0, 0, 0, 1], [1, 3.0, 6.0, 0, 0, 1]]
+        result = prox.multi_port_stats_diff(t1, t2, 1)
+
+        self.assertListEqual(result, expected)
+
+        result = prox.multi_port_stats_diff(t4, t3, 1)
+        expected = [[0, 1.0, 1.0, 0, 0, 1], [1, 1.0, 1.0, 0, 0, 1]]
+
+        self.assertListEqual(result, expected)
+
+        prox.get_string = mock.MagicMock(return_value=(True, '0,2,4,6,8,10'))
+        ok, t5 = prox.multi_port_stats([0, 1])
+        self.assertFalse(ok)
+        self.assertListEqual(t5, [])
+
+        result = prox.multi_port_stats_diff(t5, t4, 1)
+        expected = [[0, 0.0, 0.0, 0, 0, 0], [1, 0.0, 0.0, 0, 0, 0]]
+        self.assertListEqual(result, expected)
+
+        prox.get_string = mock.MagicMock(return_value=(True, '0,10,10,20,30,0;1,30,40,50,60,0'))
+        _, t6 = prox.multi_port_stats([0, 1])
+
+        prox.get_string = \
+            mock.MagicMock(return_value=(True, '0,100,100,100,100,0;1,100,100,100,100,0'))
+        _, t7 = prox.multi_port_stats([0, 1])
+
+        result = prox.multi_port_stats_diff(t6, t7, 1)
+        expected = [[0, 0.0, 0.0, 0, 0, 0], [1, 0.0, 0.0, 0, 0, 0]]
+        self.assertListEqual(result, expected)
+
+        result = prox.multi_port_stats_diff(t1, t2, 0)
+        expected = [[0, 0.0, 0.0, 0, 0, 1], [1, 0.0, 0.0, 0, 0, 1]]
+        self.assertListEqual(result, expected)
+
+    @mock.patch.object(prox_helpers.LOG, 'error')
+    def test_multi_port_stats_tuple(self, *args):
+        mock_socket = mock.MagicMock()
+        prox = prox_helpers.ProxSocketHelper(mock_socket)
+        prox.get_string = mock.MagicMock(return_value=(True, '0,1,2,3,4,5;1,1,2,3,4,5'))
+        _, result1 = prox.multi_port_stats([0, 1])
+        prox.get_string = mock.MagicMock(return_value=(True, '0,2,4,6,8,6;1,4,8,16,32,6'))
+        _, result2 = prox.multi_port_stats([0, 1])
+
+        result = prox.multi_port_stats_diff(result1, result2, 1)
+
+        vnfd_helper = mock.MagicMock()
+        vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+
+        expected = {'xe0': {'in_packets': 1.0, 'out_packets': 2.0},
+                    'xe1': {'in_packets': 3.0, 'out_packets': 6.0}}
+        live_stats = prox.multi_port_stats_tuple(result, vnfd_helper.ports_iter())
+        self.assertDictEqual(live_stats, expected)
+
+        live_stats = prox.multi_port_stats_tuple(result, None)
+        expected = {}
+        self.assertDictEqual(live_stats, expected)
+
+        live_stats = prox.multi_port_stats_tuple(None, vnfd_helper.ports_iter())
+        self.assertDictEqual(live_stats, expected)
+
     def test_port_stats(self):
         port_stats = [
             ','.join(str(n) for n in range(3, 15)),
@@ -1568,8 +1644,83 @@ class TestProxResourceHelper(unittest.TestCase):
         helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
         helper._queue = queue = mock.MagicMock()
         helper._result = {'z': 123}
+
+        helper.client = mock.MagicMock()
+        helper.client.hz.return_value = 1
+        helper.client.multi_port_stats.return_value = \
+            (True, [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]])
+        helper.client.multi_port_stats_diff.return_value = \
+            ([0, 1, 2, 3, 4, 5, 6, 7])
+        helper.client.multi_port_stats_tuple.return_value = \
+            {"xe0": {"in_packets": 1, "out_packets": 2}}
+        helper.resource = resource = mock.MagicMock()
+
+        vnfd_helper = mock.MagicMock()
+        vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+        helper.vnfd_helper = vnfd_helper
+
+        resource.check_if_system_agent_running.return_value = 0, '1234'
+        resource.amqp_collect_nfvi_kpi.return_value = 543
+        resource.check_if_system_agent_running.return_value = (0, None)
+
+        queue.empty.return_value = False
+        queue.get.return_value = {'a': 789}
+
+        expected = {'z': 123, 'a': 789,
+                    'collect_stats': {'core': 543},
+                    'live_stats': {'xe0': {'in_packets': 1, 'out_packets': 2}}}
+        result = helper.collect_kpi()
+        self.assertDictEqual(result, expected)
+
+    def test_collect_kpi_no_hz(self):
+        helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
+        helper._queue = queue = mock.MagicMock()
+        helper._result = {'z': 123}
+
+        helper.client = mock.MagicMock()
+        helper.client.multi_port_stats.return_value = \
+            (True, [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]])
+        helper.client.multi_port_stats_diff.return_value = \
+            ([0, 1, 2, 3, 4, 5, 6, 7])
+        helper.client.multi_port_stats_tuple.return_value = \
+            {"xe0": {"in_packets": 1, "out_packets": 2}}
+        helper.resource = resource = mock.MagicMock()
+
+        vnfd_helper = mock.MagicMock()
+        vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+        helper.vnfd_helper = vnfd_helper
+
+        resource.check_if_system_agent_running.return_value = 0, '1234'
+        resource.amqp_collect_nfvi_kpi.return_value = 543
+        resource.check_if_system_agent_running.return_value = (0, None)
+
+        queue.empty.return_value = False
+        queue.get.return_value = {'a': 789}
+
+        expected = {'z': 123, 'a': 789,
+                    'collect_stats': {'core': 543},
+                    'live_stats': {'xe0': {'in_packets': 1, 'out_packets': 2}}}
+        result = helper.collect_kpi()
+        self.assertDictEqual(result, expected)
+
+    def test_collect_kpi_bad_data(self):
+        helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
+        helper._queue = queue = mock.MagicMock()
+        helper._result = {'z': 123}
+
+        helper.client = mock.MagicMock()
+        helper.client.multi_port_stats.return_value = \
+            (False, [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]])
+        helper.client.multi_port_stats_diff.return_value = \
+            ([0, 1, 2, 3, 4, 5, 6, 7])
+        helper.client.multi_port_stats_tuple.return_value = \
+            {"xe0": {"in_packets": 1, "out_packets": 2}}
         helper.resource = resource = mock.MagicMock()
 
+        vnfd_helper = mock.MagicMock()
+        vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+        helper.vnfd_helper = vnfd_helper
+
         resource.check_if_system_agent_running.return_value = 0, '1234'
         resource.amqp_collect_nfvi_kpi.return_value = 543
         resource.check_if_system_agent_running.return_value = (0, None)
@@ -1577,7 +1728,8 @@ class TestProxResourceHelper(unittest.TestCase):
         queue.empty.return_value = False
         queue.get.return_value = {'a': 789}
 
-        expected = {'z': 123, 'a': 789, 'collect_stats': {'core': 543}}
+        expected = {'z': 123, 'a': 789,
+                    'collect_stats': {'core': 543}}
         result = helper.collect_kpi()
         self.assertDictEqual(result, expected)
 
index a7e61da..935d3fa 100644 (file)
@@ -329,13 +329,27 @@ class TestProxTrafficGen(unittest.TestCase):
         }
         prox_traffic_gen._vnf_wrapper.resource_helper.resource = mock.MagicMock(
             **{"self.check_if_system_agent_running.return_value": [False]})
+
+        vnfd_helper = mock.MagicMock()
+        vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+        prox_traffic_gen.resource_helper.vnfd_helper = vnfd_helper
+
+        prox_traffic_gen._vnf_wrapper.resource_helper.client = mock.MagicMock()
+        prox_traffic_gen._vnf_wrapper.resource_helper.client.multi_port_stats.return_value = \
+            [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]]
+        prox_traffic_gen._vnf_wrapper.resource_helper.client.multi_port_stats_diff.return_value = \
+            [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7]
+        prox_traffic_gen._vnf_wrapper.resource_helper.client.\
+            multi_port_stats_tuple.return_value = \
+                {"xe0": {"in_packets": 1, "out_packets": 2}}
+
         prox_traffic_gen._vnf_wrapper.vnf_execute = mock.Mock(return_value="")
         expected = {
-            'collect_stats': {},
+            'collect_stats': {'live_stats': {'xe0': {'in_packets': 1, 'out_packets': 2}}},
             'physical_node': 'mock_node'
         }
-        self.assertEqual(prox_traffic_gen.collect_kpi(), expected)
-
+        result = prox_traffic_gen.collect_kpi()
+        self.assertDictEqual(result, expected)
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.find_relative_file')
     @mock.patch(