CSIT-1078: Optimize input data files download and processing 66/12566/1
authorTibor Frank <tifrank@cisco.com>
Mon, 14 May 2018 12:35:46 +0000 (14:35 +0200)
committerTibor Frank <tifrank@cisco.com>
Mon, 14 May 2018 12:36:43 +0000 (14:36 +0200)
Change-Id: I973238d98d549555c0d43c91f9fd96a9209065ac
Signed-off-by: Tibor Frank <tifrank@cisco.com>
13 files changed:
resources/tools/presentation/conf.py
resources/tools/presentation/input_data_parser.py
resources/tools/presentation/pal.py
resources/tools/report_gen/conf.py [deleted file]
resources/tools/report_gen/fdio.svg [deleted file]
resources/tools/report_gen/requirements.txt [deleted file]
resources/tools/report_gen/run_improvments_tables.py [deleted file]
resources/tools/report_gen/run_plot.py [deleted file]
resources/tools/report_gen/run_report.cfg [deleted file]
resources/tools/report_gen/run_report.sh [deleted file]
resources/tools/report_gen/run_robot_data.py [deleted file]
resources/tools/report_gen/run_robot_json_data.py [deleted file]
resources/tools/report_gen/run_robot_teardown_data.py [deleted file]

index 58dd561..84890d9 100644 (file)
@@ -73,7 +73,8 @@ rst_epilog = """
 .. _TRex intallation: https://git.fd.io/csit/tree/resources/tools/trex/trex_installer.sh?h={release}
 .. _TRex driver: https://git.fd.io/csit/tree/resources/tools/trex/trex_stateless_profile.py?h={release}
 .. _VIRL topologies directory: https://git.fd.io/csit/tree/resources/tools/virl/topologies/?h={release}
-.. _VIRL images lists: https://git.fd.io/csit/tree/resources/tools/disk-image-builder/ubuntu/lists/?h={release}
+.. _VIRL ubuntu images lists: https://git.fd.io/csit/tree/resources/tools/disk-image-builder/ubuntu/lists/?h={release}
+.. _VIRL centos images lists: https://git.fd.io/csit/tree/resources/tools/disk-image-builder/centos/lists/?h={release}
 .. _VIRL nested: https://git.fd.io/csit/tree/resources/tools/disk-image-builder/nested/?h={release}
 .. _CSIT Honeycomb Functional Tests Documentation: https://docs.fd.io/csit/{release}/doc/tests.vpp.func.honeycomb.html
 .. _CSIT Honeycomb Performance Tests Documentation: https://docs.fd.io/csit/{release}/doc/tests.vpp.perf.honeycomb.html
index e12e2fb..d0f9eed 100644 (file)
@@ -251,6 +251,7 @@ class ExecutionChecker(ResultVisitor):
             self._version = str(re.search(self.REGEX_VERSION, msg.message).
                                 group(2))
             self._data["metadata"]["version"] = self._version
+            self._data["metadata"]["generated"] = msg.timestamp
             self._msg_type = None
 
     def _get_vat_history(self, msg):
@@ -748,17 +749,14 @@ class InputData(object):
         return self.data[job][build]["tests"]
 
     @staticmethod
-    def _parse_tests(job, build, get_timestamp=False):
+    def _parse_tests(job, build):
         """Process data from robot output.xml file and return JSON structured
         data.
 
         :param job: The name of job which build output data will be processed.
         :param build: The build which output data will be processed.
-        :param get_timestamp: If True, timestamp is read form the xml source
-            file.
         :type job: str
         :type build: dict
-        :type get_timestamp: bool
         :returns: JSON data structure.
         :rtype: dict
         """
@@ -767,10 +765,6 @@ class InputData(object):
             "job": job,
             "build": build
         }
-        if get_timestamp:
-            tree = ET.parse(build["file-name"])
-            root = tree.getroot()
-            metadata["generated"] = root.attrib["generated"]
 
         with open(build["file-name"], 'r') as data_file:
             try:
@@ -784,20 +778,16 @@ class InputData(object):
 
         return checker.data
 
-    def download_and_parse_data(self, get_timestamp=False):
+    def download_and_parse_data(self):
         """Download the input data files, parse input data from input files and
         store in pandas' Series.
-
-        :param get_timestamp: If True, timestamp is read form the xml source
-            file.
-        :type get_timestamp: bool
         """
 
         logging.info("Downloading and parsing input files ...")
 
         job_data = dict()
         for job, builds in self._cfg.builds.items():
-            logging.info("  Processing data from the job '{0}' ...'".
+            logging.info("  Processing data from the job '{0}' ...".
                          format(job))
             builds_data = dict()
             for build in builds:
@@ -813,8 +803,7 @@ class InputData(object):
 
                 logging.info("      Processing data from the build '{0}' ...".
                              format(build["build"]))
-                data = InputData._parse_tests(job, build,
-                                              get_timestamp=get_timestamp)
+                data = InputData._parse_tests(job, build)
                 if data is None:
                     logging.error("Input data file from the job '{job}', build "
                                   "'{build}' is damaged. Skipped.".
index 2268801..1ccefd3 100644 (file)
@@ -96,11 +96,7 @@ def main():
         prepare_static_content(spec)
 
         data = InputData(spec)
-
-        if spec.output["output"] == "report":
-            data.download_and_parse_data(get_timestamp=False)
-        elif spec.output["output"] == "CPTA":
-            data.download_and_parse_data(get_timestamp=True)
+        data.download_and_parse_data()
 
         generate_tables(spec, data)
         generate_plots(spec, data)
@@ -114,12 +110,12 @@ def main():
             logging.info("Successfully finished.")
         ret_code = 0
 
-    except (KeyError, ValueError, PresentationError) as err:
-        logging.info("Finished with an error.")
-        logging.critical(str(err))
-    except Exception as err:
-        logging.info("Finished with an unexpected error.")
-        logging.critical(str(err))
+    except (KeyError, ValueError, PresentationError) as err:
+        logging.info("Finished with an error.")
+        logging.critical(str(err))
+    except Exception as err:
+        logging.info("Finished with an unexpected error.")
+        logging.critical(str(err))
     finally:
         if spec is not None:
             clean_environment(spec.environment)
diff --git a/resources/tools/report_gen/conf.py b/resources/tools/report_gen/conf.py
deleted file mode 100644 (file)
index c0eb989..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# CSIT 17.01 report documentation build configuration file, created by
-# sphinx-quickstart on Sun Jan 15 09:49:36 2017.
-#
-# This file is execfile()d with the current directory set to its
-# containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#
-import os
-import sys
-
-sys.path.insert(0, os.path.abspath('.'))
-
-# -- General configuration ------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#
-# needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = ['sphinxcontrib.programoutput',
-              'sphinx.ext.ifconfig']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-#
-source_suffix = ['.rst', '.md']
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'FD.io CSIT'
-copyright = u'2017, FD.io'
-author = u'FD.io CSIT'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-#version = u''
-# The full version, including alpha/beta/rc tags.
-#release = u''
-
-rst_epilog = """
-.. |release-1| replace:: rls1704
-.. |vpp-release| replace:: VPP-17.07 release
-.. |vpp-release-1| replace:: VPP-17.04 release
-.. |dpdk-release| replace:: DPDK 17.05
-.. |trex-release| replace:: TRex v2.25
-.. |virl-image-ubuntu| replace:: ubuntu-16.04.1_2017-02-23_1.8
-.. |virl-image-centos| replace:: centos-7.3-1611_2017-02-23_1.4
-
-.. _tag documentation rst file: https://git.fd.io/csit/tree/docs/tag_documentation.rst?h=rls1707
-.. _TRex intallation: https://git.fd.io/csit/tree/resources/tools/trex/trex_installer.sh?h=rls1707
-.. _TRex driver: https://git.fd.io/csit/tree/resources/tools/trex/trex_stateless_profile.py?h=rls1707
-.. _VIRL topologies directory: https://git.fd.io/csit/tree/resources/tools/virl/topologies/?h=rls1707
-.. _VIRL ubuntu images lists: https://git.fd.io/csit/tree/resources/tools/disk-image-builder/ubuntu/lists/?h=rls1707
-.. _VIRL centos images lists: https://git.fd.io/csit/tree/resources/tools/disk-image-builder/centos/lists/?h=rls1707
-.. _VIRL nested: https://git.fd.io/csit/tree/resources/tools/disk-image-builder/nested/?h=rls1707
-.. _CSIT Honeycomb Functional Tests Documentation: https://docs.fd.io/csit/rls1707/doc/tests.vpp.func.honeycomb.html
-.. _CSIT Honeycomb Performance Tests Documentation: https://docs.fd.io/csit/rls1707/doc/tests.vpp.perf.honeycomb.html
-.. _CSIT DPDK Performance Tests Documentation: https://docs.fd.io/csit/rls1707/doc/tests.dpdk.perf.html
-.. _CSIT VPP Functional Tests Documentation: https://docs.fd.io/csit/rls1707/doc/tests.vpp.func.html
-.. _CSIT VPP Performance Tests Documentation: https://docs.fd.io/csit/rls1707/doc/tests.vpp.perf.html
-.. _CSIT NSH_SFC Functional Tests Documentation: https://docs.fd.io/csit/rls1707/doc/tests.nsh_sfc.func.html
-.. _VPP test framework documentation: https://docs.fd.io/vpp/17.07/vpp_make_test/html/
-.. _FD.io test executor vpp performance jobs: https://jenkins.fd.io/view/csit/job/csit-vpp-perf-1707-all
-.. _FD.io test executor vpp functional jobs: https://jenkins.fd.io/view/csit/job/csit-vpp-functional-1707-ubuntu1604-virl/lastSuccessfulBuild
-.. _FD.io test executor dpdk performance jobs: https://jenkins.fd.io/view/csit/job/csit-dpdk-perf-1707-all
-.. _FD.io test executor Honeycomb functional jobs: https://jenkins.fd.io/view/csit/job/hc2vpp-csit-integration-1707-ubuntu1604/lastSuccessfulBuild
-.. _FD.io test executor honeycomb performance jobs: https://jenkins.fd.io/view/hc2vpp/job/hc2vpp-csit-perf-master-ubuntu1604/lastSuccessfulBuild
-.. _FD.io test executor NSH_SFC functional jobs: https://jenkins.fd.io/view/csit/job/csit-nsh_sfc-verify-func-1707-ubuntu1604-virl/lastSuccessfulBuild
-.. _FD.io VPP compile job: https://jenkins.fd.io/view/vpp/job/vpp-merge-1707-ubuntu1604/
-.. _CSIT Testbed Setup: https://git.fd.io/csit/tree/resources/tools/testbed-setup/README.md?h=rls1707
-"""
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = 'en'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-# This patterns also effect to html_static_path and html_extra_path
-exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# If true, `todo` and `todoList` produce output, else they produce nothing.
-todo_include_todos = False
-
-# -- Options for HTML output ----------------------------------------------
-
-# The theme to use for HTML and HTML Help pages.  See the documentation for
-# a list of builtin themes.
-#
-html_theme = 'sphinx_rtd_theme'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further.  For a list of options available for each theme, see the
-# documentation.
-#
-# html_theme_options = {}
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_theme_path = ['env/lib/python2.7/site-packages/sphinx_rtd_theme']
-
-html_static_path = ['../../../docs/report/_static']
-
-html_context = {
-    'css_files': [
-        '_static/theme_overrides.css',  # overrides for wide tables in RTD theme
-        ],
-    }
-
-# -- Options for LaTeX output ---------------------------------------------
-
-latex_engine = 'pdflatex'
-
-latex_elements = {
-     # The paper size ('letterpaper' or 'a4paper').
-     #
-     'papersize': 'a4paper',
-
-     # The font size ('10pt', '11pt' or '12pt').
-     #
-     #'pointsize': '10pt',
-
-     # Additional stuff for the LaTeX preamble.
-     #
-     'preamble': r'''
-         \usepackage{pdfpages}
-         \usepackage{svg}
-         \usepackage{charter}
-         \usepackage[defaultsans]{lato}
-         \usepackage{inconsolata}
-     ''',
-
-     # Latex figure (float) alignment
-     #
-     'figure_align': 'H',
-
-     # Latex font setup
-     #
-     'fontpkg': r'''
-         \renewcommand{\familydefault}{\sfdefault}
-     ''',
-
-     # Latex other setup
-     #
-     'extraclassoptions': 'openany',
-     'sphinxsetup': r'''
-         TitleColor={RGB}{225,38,40},
-         InnerLinkColor={RGB}{62,62,63},
-         OuterLinkColor={RGB}{225,38,40},
-         shadowsep=0pt,
-         shadowsize=0pt,
-         shadowrule=0pt
-     '''
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-#  author, documentclass [howto, manual, or own class]).
-latex_documents = [
-    (master_doc, 'csit.tex', u'CSIT REPORT',
-     u'', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#
-# latex_logo = 'fdio.pdf'
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#
-# latex_use_parts = True
-
-# If true, show page references after internal links.
-#
-latex_show_pagerefs = True
-
-# If true, show URL addresses after external links.
-#
-latex_show_urls = 'footnote'
-
-# Documents to append as an appendix to all manuals.
-#
-# latex_appendices = []
-
-# It false, will not define \strong, \code,    itleref, \crossref ... but only
-# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
-# packages.
-#
-# latex_keep_old_macro_names = True
-
-# If false, no module index is generated.
-#
-# latex_domain_indices = True
diff --git a/resources/tools/report_gen/fdio.svg b/resources/tools/report_gen/fdio.svg
deleted file mode 100644 (file)
index f0dcc87..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r
-<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="630px" height="394px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"\r
-viewBox="0 0 94500000 59062500"\r
- xmlns:xlink="http://www.w3.org/1999/xlink">\r
- <defs>\r
-  <style type="text/css">\r
-   <![CDATA[\r
-    .fil2 {fill:#3C4641}\r
-    .fil1 {fill:#3E4742}\r
-    .fil0 {fill:#ED3341}\r
-   ]]>\r
-  </style>\r
- </defs>\r
- <g id="Layer_x0020_1">\r
-  <path class="fil0" d="M42892251 15970973c234833,2555989 1402971,3784607 3633525,3195163 64614,-17483 464586,-605509 524121,-613778 100406,-13939 -325789,592397 -234951,589562 663981,-21026 1166839,235659 2703054,-1575788 -125567,2507794 385088,1931698 753047,3733577 -1039736,2409632 -1745415,307125 -1486485,4471622 -4668654,-2126 -6967721,-648979 -9839813,2159679 -1571417,1536924 -3134683,5759184 -3805515,8365022 -725760,124740 -1467939,37800 -1887401,510536 -484194,545619 -431747,1408050 35674,1833418 379890,345516 987289,308424 1519678,355793 800769,71348 1142151,473327 1136244,1236651 -6615,848964 -451001,1192826 -1631306,1191054 -3702746,-5316 -8320961,16538 -11713866,45596 -1026624,8741 -1698992,464822 -1746714,1344971 -50676,931416 521640,1260039 1499833,1295831 4286993,156988 8304069,-117653 12887201,141041 783996,103714 1189755,583183 1168256,1106004 -35201,855461 -707923,1099626 -1411594,1145104 -5730598,370440 -13969581,-91665 -19611231,141278 -797344,32839 -1694621,179786 -1702890,1222476 -6615,840459 589798,1177943 1399899,1281538 2377738,7088 5327556,1418 7519956,1890 2596151,591 5192775,4134 7788926,-118l-1007843 3222096 9601909 24334 3086606 -8484328c2943911,-111628 4325029,-862076 6023666,-2197361 944528,-742534 2909773,-3271590 3377903,-4985466l-6699578 -78081 1196016 -3619114c2873627,-19727 7980761,562984 10127447,-748913 1534089,-937440 4106970,-3980458 4422954,-6498411 -1731358,-38863 -8963443,287753 -9479649,-290469 -811991,-1588073 1028633,-2402426 1978121,-3132911 1388678,-1068441 1793846,-1560904 1785578,-3760746 230108,313386 87413,679809 294368,826048 502740,355320 1446913,224319 3038411,773010 1055447,363943 2115855,607399 3274661,404696 606218,-105958 570662,-121196 999692,-407413 -87767,-924683 -247472,-1025089 -709813,-1469003 1446086,654176 966617,1888937 966499,3676168 0,1623983 504512,3115429 -2599,4527259 -1397891,3892219 -3372351,4768234 -4125752,6086745l4834856 25043 -4320540 12061626c-2523504,20318 -10295893,-341499 -12094937,331459 -2551264,954568 -5105126,4809341 -5427844,6962878 3747398,-8151 17429226,243219 20078179,-244755 5769579,-1062534 6837902,-6323231 8783066,-11759344 1441716,-4029244 5291646,-11853371 -1699464,-14191183 -1193535,-382253 -1853145,-295667 -2077228,-395955 -216523,-96863 4489,-368078 -1209600,-1404861 -1196488,-1140379 -417690,-2367934 118716,-3662820 1265001,-3005691 3370461,-2733058 3370343,-6944096 -236,-4388934 2680611,-3141771 3022583,-4763627 307479,-1458135 -1345326,-645317 -2307336,-1215388 -794273,-470610 -170809,-694693 -1801524,-842940l-178251 -1084151c-406114,246999 -713003,925509 -824631,912870 -159705,-18191 -35083,-801478 -213216,-759780 -33075,7796 -73828,19845 -123323,42643 -162068,75009 -368668,285036 -609053,585900 -1161759,1454355 -3112358,5035433 -4642076,5789779 -3004746,1481878 -5309719,91074 -10962709,3162206 -2587056,1405451 -4703383,1914216 -7362259,348233z"/>\r
-  <path class="fil1" d="M81444116 48006591c-917831,-4596598 5486670,-5710989 6489669,-1741753 1221649,4834502 -5678387,5805017 -6489669,1741753zm1873463 -5811986c-6608858,1801052 -4202297,11851718 2867130,10021253 6433324,-1665681 4111577,-11922947 -2867130,-10021253z"/>\r
-  <polygon class="fil2" points="76840667,42255321 75263698,42301508 75172978,52072571 76944144,52066547 "/>\r
-  <path class="fil1" d="M70635206 52314137c1084388,307834 2141370,-714302 1520859,-1977413 -474863,-966853 -2784797,-983627 -2488776,930589 89421,578931 388041,882158 967916,1046824z"/>\r
-  <path class="fil1" d="M76175978 40542272c695402,-45006 1114037,-372448 1062889,-1137426 -18309,-275349 -120251,-539595 -294013,-710876 -609761,-601611 -1840151,-411548 -1952016,509001 -111628,919485 435173,1387733 1183140,1339301z"/>\r
-  <path class="fil0" d="M14086524 36346354l15995897 0c719972,0 1308943,589089 1308943,1308943l0 0c0,719854 -589089,1308943 -1308943,1308943l-15995897 0c-719736,0 -1308943,-588971 -1308943,-1308943l0 0c0,-719972 589089,-1308943 1308943,-1308943z"/>\r
-  <path class="fil0" d="M20652975 31242173l13718919 0c719972,0 1308943,589326 1308943,1308943l0 118c0,719618 -589208,1308943 -1308943,1308943l-13718919 0c-719736,0 -1308943,-588971 -1308943,-1308943l0 -118c0,-719972 588971,-1308943 1308943,-1308943z"/>\r
-  <path class="fil0" d="M6885624 46609763l3154410 0c719972,0 1308943,589208 1308943,1308943l0 0c0,719736 -589326,1308943 -1308943,1308943l-3154410 0c-719736,0 -1308943,-588971 -1308943,-1308943l0 0c0,-719972 588971,-1308943 1308943,-1308943z"/>\r
- </g>\r
-</svg>\r
diff --git a/resources/tools/report_gen/requirements.txt b/resources/tools/report_gen/requirements.txt
deleted file mode 100644 (file)
index fc0ff8c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-Sphinx
-sphinx-rtd-theme
-plotly
-lxml==3.5.0
-robotframework==2.9.2
-sphinxcontrib-programoutput
diff --git a/resources/tools/report_gen/run_improvments_tables.py b/resources/tools/report_gen/run_improvments_tables.py
deleted file mode 100755 (executable)
index ebdfd60..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2017 Cisco and/or its affiliates.
-# 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.
-
-"""Generate csv files for the chapter "CSIT Release Notes" from json files
-generated by Jenkins' jobs.
-"""
-
-from sys import exit as sys_exit
-from os import walk
-from os.path import join
-from math import sqrt
-from argparse import ArgumentParser, RawDescriptionHelpFormatter
-from json import load
-
-
-EXT_JSON = ".json"
-EXT_TMPL = ".template"
-EXT_CSV = ".csv"
-
-
-def get_files(path, extension):
-    """Generates the list of files to process.
-
-    :param path: Path to files.
-    :param extension: Extension of files to process. If it is the empty string,
-    all files will be processed.
-    :type path: str
-    :type extension: str
-    :returns: List of files to process.
-    :rtype: list
-    """
-
-    file_list = list()
-    for root, _, files in walk(path):
-        for filename in files:
-            if extension:
-                if filename.endswith(extension):
-                    file_list.append(join(root, filename))
-            else:
-                file_list.append(join(root, filename))
-
-    return file_list
-
-
-def parse_args():
-    """Parse arguments from cmd line.
-
-    :returns: Parsed arguments.
-    :rtype ArgumentParser
-    """
-
-    parser = ArgumentParser(description=__doc__,
-                            formatter_class=RawDescriptionHelpFormatter)
-    parser.add_argument("-i", "--input",
-                        required=True,
-                        help="Input folder with data files.")
-    parser.add_argument("-o", "--output",
-                        required=True,
-                        help="Output folder with csv files and templates for "
-                             "csv files.")
-    return parser.parse_args()
-
-
-def calculate_stats(data):
-    """Calculate statistics:
-    - average,
-    - standard deviation.
-
-    :param data: Data to process.
-    :type data: list
-    :returns: Average and standard deviation.
-    :rtype: tuple
-    """
-
-    if len(data) == 0:
-        return None, None
-
-    def average(items):
-        """Calculate average from the items.
-
-        :param items: Average is calculated from these items.
-        :type items: list
-        :returns: Average.
-        :rtype: float
-        """
-        return float(sum(items)) / len(items)
-
-    avg = average(data)
-    variance = [(x - avg) ** 2 for x in data]
-    stdev = sqrt(average(variance))
-
-    return avg, stdev
-
-
-def write_line_to_file(file_handler, item):
-    """Write a line to the csv file.
-
-    :param file_handler: File handler for the csv file. It must be open for
-     writing text.
-    :param item: Item to be written to the file.
-    :type file_handler: BinaryIO
-    :type item: dict
-    """
-
-    mean = "" if item["mean"] is None else "{:.1f}".format(item["mean"])
-    stdev = "" if item["stdev"] is None else "{:.1f}".format(item["stdev"])
-    change = "" if item["change"] is None else "{:.0f}%".format(item["change"])
-    file_handler.write("{},{},{},{}\n".format(item["old"], mean, stdev, change))
-
-
-def main():
-    """Main function to generate csv files for the chapter "CSIT Release Notes"
-    from json files generated by Jenkins' jobs.
-    """
-
-    args = parse_args()
-
-    json_files = get_files(args.input, EXT_JSON)
-    tmpl_files = get_files(args.output, EXT_TMPL)
-
-    if len(json_files) == 0:
-        print("No json data to process.")
-        exit(1)
-
-    if len(tmpl_files) == 0:
-        print("No template files to process.")
-        exit(1)
-
-    # Get information from template files
-    csv_data = list()
-    for tmpl_file in tmpl_files:
-        with open(tmpl_file, mode='r') as file_handler:
-            for line in file_handler:
-                line_list = line.split(',')
-                try:
-                    csv_data.append({
-                        "ID": line_list[0],
-                        "type": line_list[0].rsplit("-", 1)[-1],
-                        "old": ",".join(line_list[1:])[:-1],
-                        "last_old": line_list[-1][:-1],
-                        "rates": list(),
-                        "mean": None,
-                        "stdev": None,
-                        "change": None})
-                except IndexError:
-                    pass
-
-    # Update existing data with the new information from json files
-    for json_file in json_files:
-        with open(json_file) as file_handler:
-            tests_data = load(file_handler)
-            for item in csv_data:
-                try:
-                    rate = tests_data["data"][item["ID"]]["throughput"]["value"]
-                    item["rates"].append(rate)
-                except KeyError:
-                    pass
-
-    # Add statistics
-    for item in csv_data:
-        mean, stdev = calculate_stats(item["rates"])
-        if mean is not None:
-            mean = float(mean) / 1000000
-            old = float(item["last_old"]) if item["last_old"] else None
-            item["mean"] = mean
-            item["change"] = ((round(mean, 1) - round(old, 1)) / round(old, 1))\
-                * 100 if old else None
-            item["stdev"] = stdev / 1000000
-
-    # Sort the list, key = change
-    csv_data.sort(key=lambda data: data["change"], reverse=True)
-
-    # Write csv files
-    for tmpl_file in tmpl_files:
-        csv_file = tmpl_file.replace(EXT_TMPL, EXT_CSV)
-        with open(csv_file, "w") as file_handler:
-            for item in csv_data:
-                if "pdr_" in csv_file \
-                        and "_others" not in csv_file \
-                        and item["type"] == "pdrdisc" \
-                        and item["change"] >= 9.5:
-                    write_line_to_file(file_handler, item)
-                elif "pdr_" in csv_file \
-                        and "_others" in csv_file \
-                        and item["type"] == "pdrdisc" \
-                        and item["change"] < 9.5:
-                    write_line_to_file(file_handler, item)
-                elif "ndr_" in csv_file \
-                        and "_others" not in csv_file \
-                        and item["type"] == "ndrdisc" \
-                        and item["change"] >= 9.5:
-                    write_line_to_file(file_handler, item)
-                elif "ndr_" in csv_file \
-                        and "_others" in csv_file \
-                        and item["type"] == "ndrdisc" \
-                        and item["change"] < 9.5:
-                    write_line_to_file(file_handler, item)
-
-
-if __name__ == "__main__":
-    sys_exit(main())
diff --git a/resources/tools/report_gen/run_plot.py b/resources/tools/report_gen/run_plot.py
deleted file mode 100644 (file)
index 0a95396..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2016 Cisco and/or its affiliates.
-# 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.
-
-"""Plot the performance data"""
-
-import argparse
-import operator
-import os
-import sys
-import math
-
-import plotly.offline as ploff
-import plotly.graph_objs as plgo
-from lxml import etree
-
-
-def select_files_in_subfolders(directory, ext='xml'):
-    """Get all files in folder and its subfolders.
-
-    :param dir: Input folder.
-    :param ext: File extension.
-    :type dir: str
-    :type ext: str
-    :return: List of filex matching the parameters.
-    :rtype list
-    """
-    for _, _, files in os.walk(directory):
-        for file in files:
-            if file.endswith('.%s' % ext):
-                yield os.path.join(directory, file)
-
-
-def select_files_in_folder(directory, ext='xml'):
-    """Get all files in folder.
-
-    :param dir: Input folder.
-    :param ext: File extension.
-    :type dir: str
-    :type ext: str
-    :return: List of filex matching the parameters.
-    :rtype list
-    """
-    for file in os.listdir(directory):
-        if file.endswith('.%s' % ext):
-            yield os.path.join(directory, file)
-
-
-def combine_dicts(first, second, oper=operator.add):
-    """Combine two dictionaries.
-
-    :param first: First dict.
-    :param second: Second dict.
-    :param oper: Operator.
-    :type first: dict
-    :type second: dict
-    :type oper: operator
-    :return: Combined dictionary.
-    :rtype dict
-    """
-
-    return dict(first.items() + second.items() +\
-        [(k, oper(first[k], second[k])) for k in set(second) & set(first)])
-
-
-def parse_data_pps(args):
-    """Get PPS data out of XML file into array.
-
-    :param args: Command line parameters.
-    :type suite: ArgumentParser
-    :return: X-data and Y-data dictionaries.
-    :rtype tuple of dict
-    """
-    xdata = []
-    ydata_pps = {}
-
-    for i, file in enumerate(sorted(select_files_in_folder(args.input))):
-        xml_tree = etree.parse(file)
-        sel = xml_tree.xpath(args.xpath)
-        if sel:
-            ydata_pps = combine_dicts(ydata_pps, dict((elem.attrib['name'],\
-                (i, float(elem.text))) for elem in sel))
-            xdata.append(xml_tree.getroot().attrib['vdevice'])
-    return xdata, ydata_pps
-
-
-def parse_data_lat(args):
-    """Get latency data out of XML file into array.
-
-    :param args: Command line parameters.
-    :type suite: ArgumentParser
-    :return: X-data and Y-data dictionaries.
-    :rtype tuple of dict
-    """
-    xdata = []
-    ydata_lat = {}
-
-    for i, file in enumerate(sorted(select_files_in_folder(args.input))):
-        xml_tree = etree.parse(file)
-        sel = xml_tree.xpath(args.xpath)
-        if sel:
-            try:
-                ydata_lat = combine_dicts(ydata_lat, dict((elem.attrib['name'],\
-                    (i, elem.attrib[args.latency])) for elem in sel))
-            except KeyError:
-                raise RuntimeError('Retrieving latency data error (PDR?)')
-            xdata.append(xml_tree.getroot().attrib['vdevice'])
-    return xdata, ydata_lat
-
-
-def parse_args():
-    """Parse arguments from cmd line.
-
-    :return: Parsed arguments.
-    :rtype ArgumentParser
-    """
-
-    parser = argparse.ArgumentParser()
-    parser.add_argument("-x", "--xpath", required=True,
-                        help="Xpath filter")
-    parser.add_argument("-t", "--title", required=True,
-                        help="Plot title")
-    parser.add_argument("-l", "--lower",
-                        default=False,
-                        help="Lower boudary of Y-axis")
-    parser.add_argument("-u", "--upper",
-                        default=False,
-                        help="Upper boudary of Y-axis")
-    parser.add_argument("-e", "--errorbar",
-                        default=False,
-                        help="Errorbar for Y-axis")
-    parser.add_argument("-d", "--latency",
-                        choices=['lat_10', 'lat_50', 'lat_100'],
-                        help="Latency to draw")
-    parser.add_argument("-p", "--plot",
-                        choices=['box', 'scatter'],
-                        default='box',
-                        help="Throughput plot type")
-    parser.add_argument("-i", "--input",
-                        help="Input folder")
-    parser.add_argument("-o", "--output", required=True,
-                        help="Output image file name")
-    return parser.parse_args()
-
-
-def main():
-    """Main function."""
-
-    args = parse_args()
-    if args.latency:
-        xdata, ydata = parse_data_lat(args)
-    else:
-        xdata, ydata = parse_data_pps(args)
-
-    # Print data into console for debug
-    print args.title
-    for data in ydata:
-        print data + ";" + ";".join(str(val) for val in ydata[data][1::2])
-
-    if xdata and ydata:
-        traces = []
-        # Add plot traces
-        for i, suite in enumerate(ydata):
-            if args.latency:
-                y_extract = []
-                _ = [y_extract.extend([l, l]) for l in ydata[suite][1::2][0].split('/')]
-                traces.append(plgo.Box(
-                    x=['TGint1-to-SUT1-to-SUT2-to-TGint2',
-                       'TGint1-to-SUT1-to-SUT2-to-TGint2',
-                       'TGint1-to-SUT1-to-SUT2-to-TGint2',
-                       'TGint1-to-SUT1-to-SUT2-to-TGint2',
-                       'TGint1-to-SUT1-to-SUT2-to-TGint2',
-                       'TGint1-to-SUT1-to-SUT2-to-TGint2',
-                       'TGint2-to-SUT2-to-SUT1-to-TGint1',
-                       'TGint2-to-SUT2-to-SUT1-to-TGint1',
-                       'TGint2-to-SUT2-to-SUT1-to-TGint1',
-                       'TGint2-to-SUT2-to-SUT1-to-TGint1',
-                       'TGint2-to-SUT2-to-SUT1-to-TGint1',
-                       'TGint2-to-SUT2-to-SUT1-to-TGint1'],
-                    y=y_extract,
-                    name=str(i+1)+'. '+suite.lower().replace('-ndrdisc',''),
-                    boxmean=False,
-                ))
-            else:
-                if args.plot == 'box':
-                    traces.append(plgo.Box(
-                        x=[str(i+1)+'.'] * len(ydata[suite][1::2]),
-                        y=ydata[suite][1::2],
-                        name=str(i+1)+'. '+suite.lower().replace('-ndrdisc',''),
-                        hoverinfo='x+y',
-                        boxpoints='outliers',
-                        whiskerwidth=0,
-                    ))
-                elif args.plot == 'scatter':
-                    traces.append(plgo.Scatter(
-                        x=ydata[suite][0::2],
-                        y=ydata[suite][1::2],
-                        mode='lines+markers',
-                        name=str(i+1)+'. '+suite.lower().replace('-ndrdisc',''),
-                    ))
-                else:
-                    pass
-
-        # Add plot layout
-        layout = plgo.Layout(
-            title='{0}'.format(args.title),
-            xaxis=dict(
-                autorange=True,
-                autotick=False,
-                fixedrange=False,
-                gridcolor='rgb(238, 238, 238)',
-                linecolor='rgb(238, 238, 238)',
-                linewidth=1,
-                showgrid=True,
-                showline=True,
-                showticklabels=True,
-                tickcolor='rgb(238, 238, 238)',
-                tickmode='linear',
-                title='Indexed Test Cases' if args.plot == 'box'\
-                    else '',
-                zeroline=False,
-            ),
-            yaxis=dict(
-                gridcolor='rgb(238, 238, 238)',
-                hoverformat='' if args.latency else '.4s',
-                linecolor='rgb(238, 238, 238)',
-                linewidth=1,
-                range=[args.lower, args.upper] if args.lower and args.upper\
-                    else [],
-                showgrid=True,
-                showline=True,
-                showticklabels=True,
-                tickcolor='rgb(238, 238, 238)',
-                title='Latency min/avg/max [uSec]' if args.latency\
-                    else 'Packets Per Second [pps]',
-                zeroline=False,
-            ),
-            boxmode='group',
-            boxgroupgap=0.5,
-            autosize=False,
-            margin=dict(
-                t=50,
-                b=20,
-                l=50,
-                r=20,
-            ),
-            showlegend=True,
-            legend=dict(
-                orientation='h',
-            ),
-            width=700,
-            height=1000,
-        )
-        # Create plot
-        plpl = plgo.Figure(data=traces, layout=layout)
-        # Export Plot
-        ploff.plot(plpl,
-                   show_link=False, auto_open=False,
-                   filename='{0}.html'.format(args.output))
-    else:
-        sys.stderr.write('No data found!\n')
-
-
-if __name__ == "__main__":
-    sys.exit(main())
diff --git a/resources/tools/report_gen/run_report.cfg b/resources/tools/report_gen/run_report.cfg
deleted file mode 100644 (file)
index b35f490..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/bash
-
-declare -r TRUE=0
-declare -r FALSE=1
-
-# set default values in config array
-typeset -A DIR
-typeset -A URL
-typeset -A JOB
-typeset -A CFG
-
-CFG[DEBUG]=0
-CFG[BLD_LATEX]=1
-CFG[BLD_HTML]=1
-
-DIR[WORKING]=_tmp
-DIR[BUILD,HTML]=_build
-DIR[BUILD,LATEX]=_build_latex
-DIR[RST]=../../../docs/report
-
-DIR[STATIC]=${DIR[BUILD,HTML]}/_static
-DIR[STATIC,VPP]=${DIR[STATIC]}/vpp
-DIR[STATIC,DPDK]=${DIR[STATIC]}/dpdk
-DIR[STATIC,ARCH]=${DIR[STATIC]}/archive
-DIR[STATIC,TREND]=${DIR[STATIC]}/trending
-
-DIR[PLOT,VPP]=${DIR[WORKING]}/vpp_plot
-DIR[PLOT,DPDK]=${DIR[WORKING]}/dpdk_plot
-
-DIR[DTR]=${DIR[RST]}/detailed_test_results
-DIR[DTR,PERF,DPDK]=${DIR[DTR]}/dpdk_performance_results
-DIR[DTR,PERF,VPP]=${DIR[DTR]}/vpp_performance_results
-DIR[DTR,PERF,HC]=${DIR[DTR]}/honeycomb_performance_results
-DIR[DTR,FUNC,VPP]=${DIR[DTR]}/vpp_functional_results
-DIR[DTR,FUNC,HC]=${DIR[DTR]}/honeycomb_functional_results
-DIR[DTR,FUNC,NSHSFC]=${DIR[DTR]}/nshsfc_functional_results
-DIR[DTR,PERF,VPP,IMPRV]=${DIR[RST]}/vpp_performance_tests/performance_improvements
-
-DIR[DTC]=${DIR[RST]}/test_configuration
-DIR[DTC,PERF,VPP]=${DIR[DTC]}/vpp_performance_configuration
-DIR[DTC,FUNC,VPP]=${DIR[DTC]}/vpp_functional_configuration
-
-DIR[DTO]=${DIR[RST]}/test_operational_data
-DIR[DTO,PERF,VPP]=${DIR[DTO]}/vpp_performance_operational_data
-
-DIR[CSS_PATCH_FILE]=${DIR[STATIC]}/theme_overrides.css
-
-URL[JENKINS,CSIT]='https://jenkins.fd.io/view/csit/job'
-URL[JENKINS,HC]='https://jenkins.fd.io/view/hc2vpp/job'
-
-JOB[PERF,VPP]=csit-vpp-perf-1707-all
-JOB[PERF,VPP,BLD]="9 10 13 14 15 16 17 18 19 21"
-JOB[PERF,VPP,FBLD]=22
-JOB[PERF,DPDK]=csit-dpdk-perf-1707-all
-JOB[PERF,DPDK,BLD]="1 2 3 4 5 6 7 8 9 10"
-JOB[PERF,DPDK,FBLD]=10
-JOB[FUNC,VPP]=csit-vpp-functional-1707-ubuntu1604-virl
-JOB[FUNC,VPP,BLD]=lastSuccessfulBuild
-JOB[PERF,HC]=hc2vpp-csit-perf-master-ubuntu1604
-JOB[PERF,HC,BLD]="8 9"
-JOB[FUNC,HC]=hc2vpp-csit-integration-1707-ubuntu1604
-JOB[FUNC,HC,BLD]=lastSuccessfulBuild
-JOB[FUNC,NSH]=csit-nsh_sfc-verify-func-1707-ubuntu1604-virl
-JOB[FUNC,NSH,BLD]=2
-
-JOB[1704,PERF,VPP]=csit-vpp-perf-1704-all
-JOB[1704,VPP,BLD]="6 7 8 9 10 12 14 15 16 17"
-JOB[1704,DPDK]=csit-dpdk-perf-1704-all
-JOB[1704,DPDK,BLD]="1 2 3 4 6 7 8 9 10 11"
diff --git a/resources/tools/report_gen/run_report.sh b/resources/tools/report_gen/run_report.sh
deleted file mode 100755 (executable)
index ec779ad..0000000
+++ /dev/null
@@ -1,627 +0,0 @@
-#!/bin/bash
-
-set -x
-
-# Script directory
-SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-# Get actual date
-DATE=$(date -u '+%d-%b-%Y')
-
-# Load configuration
-source ${SCRIPT_DIR}/run_report.cfg
-
-# Process parameters
-for i in "$@"; do
-case $i in
-    --debug)
-        CFG[DEBUG]=1
-    ;;
-    --no_latex)
-        CFG[BLD_LATEX]=0
-    ;;
-    --no_html)
-        CFG[BLD_HTML]=0
-    ;;
-    *)
-        # unknown option
-    ;;
-esac
-done
-
-# Install system dependencies
-sudo apt-get -y update
-sudo apt-get -y install libxml2 libxml2-dev libxslt-dev build-essential \
-    zlib1g-dev unzip
-if [[ ${CFG[BLD_LATEX]} -eq 1 ]] ;
-then
-    sudo apt-get -y install xvfb texlive-latex-recommended \
-        texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra latexmk wkhtmltopdf
-    sudo sed -i.bak 's/^\(main_memory\s=\s\).*/\110000000/' /usr/share/texlive/texmf-dist/web2c/texmf.cnf
-fi
-
-# Clean-up when finished
-trap 'rm -rf ${DIR[WORKING]}; exit' EXIT
-trap 'rm -rf ${DIR[WORKING]}; exit' ERR
-
-# Remove the old build
-rm -rf ${DIR[BUILD,HTML]} || true
-rm -rf ${DIR[BUILD,LATEX]} || true
-rm -rf ${DIR[WORKING]} || true
-
-# Create working directories
-mkdir ${DIR[WORKING]}
-
-# Create virtual environment
-virtualenv ${DIR[WORKING]}/env
-. ${DIR[WORKING]}/env/bin/activate
-
-# Install python dependencies:
-pip install -r requirements.txt
-
-export PYTHONPATH=`pwd`
-
-# Download raw outputs for plots
-echo Downloading raw outputs for plots ...
-mkdir -p ${DIR[STATIC,VPP]}
-mkdir -p ${DIR[STATIC,DPDK]}
-mkdir -p ${DIR[STATIC,ARCH]}
-mkdir -p ${DIR[STATIC,TREND]}
-mkdir -p ${DIR[PLOT,VPP]}
-mkdir -p ${DIR[PLOT,DPDK]}
-
-### VPP PERFORMANCE SOURCE DATA
-
-#if [[ ${CFG[DEBUG]} -eq 1 ]] ;
-#    cp ./${JOB[PERF,VPP]}-${JOB[PERF,VPP,FBLD]}.zip ${DIR[STATIC,ARCH]}/${JOB[PERF,VPP]}-${JOB[PERF,VPP,FBLD]}.zip
-#fi
-
-blds=${JOB[PERF,VPP,BLD]}
-for i in ${blds[@]}; do
-    curl --silent ${URL[JENKINS,CSIT]}/${JOB[PERF,VPP]}/${i}/robot/report/output_perf_data.xml \
-        --output ${DIR[PLOT,VPP]}/${JOB[PERF,VPP]}-${i}.xml
-    if [[ ${CFG[DEBUG]} -eq 0 ]] ;
-    then
-        curl --fail --silent ${URL[JENKINS,CSIT]}/${JOB[PERF,VPP]}/${i}/robot/report/\*zip\*/robot-plugin.zip \
-            --output ${DIR[STATIC,ARCH]}/${JOB[PERF,VPP]}-${i}.zip
-    fi
-done
-if [[ ${CFG[DEBUG]} -eq 0 ]] ;
-then
-    curl --fail --silent ${URL[JENKINS,CSIT]}/${JOB[PERF,VPP]}/${JOB[PERF,VPP,FBLD]}/robot/report/\*zip\*/robot-plugin.zip \
-        --output ${DIR[STATIC,ARCH]}/${JOB[PERF,VPP]}-${JOB[PERF,VPP,FBLD]}.zip
-fi
-# Archive trending
-cp ${DIR[PLOT,VPP]}/* ${DIR[STATIC,TREND]}
-blds=${JOB[1704,VPP,BLD]}
-for i in ${blds[@]}; do
-    curl --silent ${URL[JENKINS,CSIT]}/${JOB[1704,PERF,VPP]}/${i}/robot/report/output_perf_data.xml \
-        --output ${DIR[STATIC,TREND]}/${JOB[1704,PERF,VPP]}-${i}.xml
-done
-
-### DPDK PERFORMANCE SOURCE DATA
-
-#if [[ ${CFG[DEBUG]} -eq 1 ]] ;
-#    cp ./${JOB[PERF,DPDK]}-${JOB[PERF,DPDK,FBLD]}.zip ${DIR[STATIC,ARCH]}/${JOB[PERF,DPDK]}-${JOB[PERF,DPDK,FBLD]}.zip
-#fi
-
-blds=${JOB[PERF,DPDK,BLD]}
-for i in ${blds[@]}; do
-    curl --silent ${URL[JENKINS,CSIT]}/${JOB[PERF,DPDK]}/${i}/robot/report/output_perf_data.xml \
-        --output ${DIR[PLOT,DPDK]}/${JOB[PERF,DPDK]}-${i}.xml
-    if [[ ${CFG[DEBUG]} -eq 0 ]] ;
-    then
-        curl --fail --silent ${URL[JENKINS,CSIT]}/${JOB[PERF,DPDK]}/${i}/robot/report/\*zip\*/robot-plugin.zip \
-            --output ${DIR[STATIC,ARCH]}/${JOB[PERF,DPDK]}-${i}.zip
-    fi
-done
-cp ${DIR[PLOT,DPDK]}/* ${DIR[STATIC,TREND]}
-
-### FUNCTIONAL SOURCE DATA
-
-#if [[ ${CFG[DEBUG]} -eq 1 ]] ;
-#    cp ./${JOB[FUNC,VPP]}-${JOB[FUNC,VPP,BLD]}.zip ${DIR[STATIC,ARCH]}/${JOB[FUNC,VPP]}-${JOB[FUNC,VPP,BLD]}.zip
-#fi
-
-if [[ ${CFG[DEBUG]} -eq 0 ]] ;
-then
-    curl --fail --silent ${URL[JENKINS,CSIT]}/${JOB[FUNC,VPP]}/${JOB[FUNC,VPP,BLD]}/robot/report/\*zip\*/robot-plugin.zip \
-        --output ${DIR[STATIC,ARCH]}/${JOB[FUNC,VPP]}-${JOB[FUNC,VPP,BLD]}.zip
-fi
-
-### HONEYCOMB FUNCTIONAL SOURCE DATA
-
-#if [[ ${CFG[DEBUG]} -eq 1 ]] ;
-#    cp ./${JOB[FUNC,HC]}-${JOB[FUNC,HC,BLD]}.zip ${DIR[STATIC,ARCH]}/${JOB[FUNC,HC]}-${JOB[FUNC,HC,BLD]}.zip
-#fi
-
-if [[ ${CFG[DEBUG]} -eq 0 ]] ;
-then
-    curl --fail --silent ${URL[JENKINS,HC]}/${JOB[FUNC,HC]}/${JOB[FUNC,HC,BLD]}/robot/report/\*zip\*/robot-plugin.zip \
-        --output ${DIR[STATIC,ARCH]}/${JOB[FUNC,HC]}-${JOB[FUNC,HC,BLD]}.zip
-fi
-
-### HONEYCOMB PERFORMANCE SOURCE DATA
-
-#if [[ ${CFG[DEBUG]} -eq 1 ]] ;
-#    cp ./${JOB[PERF,HC]}-${JOB[PERF,HC,BLD]}.zip ${DIR[STATIC,ARCH]}/${JOB[PERF,HC]}-${JOB[PERF,HC,BLD]}.zip
-#fi
-
-if [[ ${CFG[DEBUG]} -eq 0 ]] ;
-then
-    blds=${JOB[PERF,HC,BLD]}
-    for i in ${blds[@]}; do
-        curl --silent ${URL[JENKINS,HC]}/${JOB[PERF,HC]}/${i}/robot/report/\*zip\*/robot-plugin.zip \
-            --output ${DIR[STATIC,ARCH]}/${JOB[PERF,HC]}-${i}.zip
-done
-fi
-
-### NSH_SFC SOURCE DATA
-
-#if [[ ${CFG[DEBUG]} -eq 1 ]] ;
-#    cp ./${JOB[FUNC,NSH]}-${JOB[FUNC,NSH,BLD]}.zip ${DIR[STATIC,ARCH]}/${JOB[FUNC,NSH]}-${JOB[FUNC,NSH,BLD]}.zip
-#fi
-
-if [[ ${CFG[DEBUG]} -eq 0 ]] ;
-then
-    curl --fail --silent ${URL[JENKINS,CSIT]}/${JOB[FUNC,NSH]}/${JOB[FUNC,NSH,BLD]}/robot/report/\*zip\*/robot-plugin.zip \
-        --output ${DIR[STATIC,ARCH]}/${JOB[FUNC,NSH]}-${JOB[FUNC,NSH,BLD]}.zip
-fi
-
-# Data post processing
-
-if [[ ${CFG[DEBUG]} -eq 0 ]] ;
-then
-    # VPP PERF
-    unzip -o ${DIR[STATIC,ARCH]}/${JOB[PERF,VPP]}-${JOB[PERF,VPP,FBLD]}.zip -d ${DIR[WORKING]}/
-    python run_robot_data.py -i ${DIR[WORKING]}/robot-plugin/output.xml \
-        --output ${DIR[DTR,PERF,VPP]}/vpp_performance_results.rst \
-        --formatting rst --start 4 --level 2
-    python run_robot_teardown_data.py -i ${DIR[WORKING]}/robot-plugin/output.xml \
-        --output ${DIR[DTC,PERF,VPP]}/vpp_performance_configuration.rst \
-        --data "VAT_H" --formatting rst --start 4 --level 2
-    python run_robot_teardown_data.py -i ${DIR[WORKING]}/robot-plugin/output.xml \
-        --output ${DIR[DTO,PERF,VPP]}/vpp_performance_operational_data.rst \
-        --data "SH_RUN" --formatting rst --start 4 --level 2
-
-    blds=${JOB[PERF,VPP,BLD]}
-    for i in ${blds[@]}; do
-        unzip -o ${DIR[STATIC,ARCH]}/${JOB[PERF,VPP]}-${i}.zip -d ${DIR[WORKING]}/
-        python run_robot_json_data.py \
-            --input ${DIR[WORKING]}/robot-plugin/output.xml \
-            --output ${DIR[DTR,PERF,VPP,IMPRV]}/${JOB[PERF,VPP]}-${i}.json \
-            --vdevice ${i}
-    done
-
-    # DPDK PERF
-    unzip -o ${DIR[STATIC,ARCH]}/${JOB[PERF,DPDK]}-${JOB[PERF,DPDK,FBLD]}.zip -d ${DIR[WORKING]}/
-    python run_robot_data.py -i ${DIR[WORKING]}/robot-plugin/output.xml \
-        --output ${DIR[DTR,PERF,DPDK]}/dpdk_performance_results.rst \
-        --formatting rst --start 4 --level 2
-
-    # VPP FUNC
-    unzip -o ${DIR[STATIC,ARCH]}/${JOB[FUNC,VPP]}-${JOB[FUNC,VPP,BLD]}.zip -d ${DIR[WORKING]}/
-    python run_robot_data.py -i ${DIR[WORKING]}/robot-plugin/output.xml \
-        --output ${DIR[DTR,FUNC,VPP]}/vpp_functional_results.rst \
-        --formatting rst --start 5 --level 2
-    python run_robot_teardown_data.py -i ${DIR[WORKING]}/robot-plugin/output.xml \
-        --output ${DIR[DTC,FUNC,VPP]}/vpp_functional_configuration.rst \
-        --data "VAT_H" --formatting rst --start 5 --level 2
-
-    # HC FUNC
-    unzip -o ${DIR[STATIC,ARCH]}/${JOB[FUNC,HC]}-${JOB[FUNC,HC,BLD]}.zip -d ${DIR[WORKING]}/
-    python run_robot_data.py -i ${DIR[WORKING]}/robot-plugin/output.xml \
-        --output ${DIR[DTR,FUNC,HC]}/honeycomb_functional_results.rst \
-        --formatting rst --start 5 --level 2
-
-    # NSHSFC FUNC
-    unzip -o ${DIR[STATIC,ARCH]}/${JOB[FUNC,NSH]}-${JOB[FUNC,NSH,BLD]}.zip -d ${DIR[WORKING]}/
-    python run_robot_data.py -i ${DIR[WORKING]}/robot-plugin/output.xml \
-        --output ${DIR[DTR,FUNC,NSHSFC]}/nshsfc_functional_results.rst \
-        --formatting rst --start 5 --level 2
-fi
-
-# Generate tables for performance improvements
-if [[ ${CFG[DEBUG]} -eq 0 ]] ;
-then
-    python run_improvments_tables.py \
-        --input ${DIR[DTR,PERF,VPP,IMPRV]} \
-        --output ${DIR[DTR,PERF,VPP,IMPRV]}
-fi
-
-# Delete temporary json files
-find ${DIR[RST]} -name "*.json" -type f -delete
-
-# Plot packets per second
-
-# VPP L2 sel1
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-l2-sel1-ndrdisc \
-    --title "64B-1t1c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]'
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-l2-sel1-ndrdisc \
-    --title "64B-2t2c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]'
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-l2-sel1-pdrdisc \
-    --title "64B-1t1c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"1T1C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-l2-sel1-pdrdisc \
-    --title "64B-2t2c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"2T2C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]'
-
-# VPP L2 sel2
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-l2-sel2-ndrdisc \
-    --title "64B-1t1c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and ((contains(@tags,"FEATURE") and contains(@tags,"ACL50") and contains(@tags,"10k_FLOWS"))) and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --lower 0 --upper 8000000
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-l2-sel2-ndrdisc \
-    --title "64B-2t2c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and ((contains(@tags,"FEATURE") and contains(@tags,"ACL50") and contains(@tags,"10k_FLOWS"))) and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --lower 5000000 --upper 12000000
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-l2-sel2-pdrdisc \
-    --title "64B-1t1c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-pdrdisc" \
-    --xpath '//*[@framesize="64B" and ((contains(@tags,"FEATURE") and contains(@tags,"ACL50") and contains(@tags,"10k_FLOWS"))) and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"1T1C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --lower 0 --upper 8000000
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-l2-sel2-pdrdisc \
-    --title "64B-2t2c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-pdrdisc" \
-    --xpath '//*[@framesize="64B" and ((contains(@tags,"FEATURE") and contains(@tags,"ACL50") and contains(@tags,"10k_FLOWS"))) and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --lower 5000000 --upper 12000000
-
-# VPP IP4
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-ethip4-ip4-ndrdisc \
-    --title "64B-1t1c-ethip4-ip4[a-z0-9]+-[a-z-]*ndrdisc" \
-    --xpath '//*[@framesize="64B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"IP4FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-ethip4-ip4-ndrdisc \
-    --title "64B-2t2c-ethip4-ip4[a-z0-9]+-[a-z-]*ndrdisc" \
-    --xpath '//*[@framesize="64B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"IP4FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]'
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-ethip4-ip4-pdrdisc \
-    --title "64B-1t1c-ethip4-ip4[a-z0-9]+-[a-z-]*pdrdisc" \
-    --xpath '//*[@framesize="64B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"1T1C") and contains(@tags,"IP4FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-ethip4-ip4-pdrdisc \
-    --title "64B-2t2c-ethip4-ip4[a-z0-9]+-[a-z-]*pdrdisc" \
-    --xpath '//*[@framesize="64B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"2T2C") and contains(@tags,"IP4FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]'
-
-# VPP IP6
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-1t1c-ethip6-ip6-ndrdisc \
-    --title "78B-1t1c-ethip6-ip6[a-z0-9]+-[a-z-]*ndrdisc" \
-    --xpath '//*[@framesize="78B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"IP6FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-2t2c-ethip6-ip6-ndrdisc \
-    --title "78B-2t2c-ethip6-ip6[a-z0-9]+-[a-z-]*ndrdisc" \
-    --xpath '//*[@framesize="78B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"IP6FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]'
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-1t1c-ethip6-ip6-pdrdisc \
-    --title "78B-1t1c-ethip6-ip6[a-z0-9]+-[a-z-]*pdrdisc" \
-    --xpath '//*[@framesize="78B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"1T1C") and contains(@tags,"IP6FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-2t2c-ethip6-ip6-pdrdisc \
-    --title "78B-2t2c-ethip6-ip6[a-z0-9]+-[a-z-]*pdrdisc" \
-    --xpath '//*[@framesize="78B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"2T2C") and contains(@tags,"IP6FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]'
-
-# VPP IP4_overlay
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-ethip4-ndrdisc \
-    --title "64B-1t1c-ethip4[a-z0-9]+-[a-z0-9]*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"ENCAP") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST")) and not(contains(@tags, "IPSECHW"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-ethip4-ndrdisc \
-    --title "64B-2t2c-ethip4[a-z0-9]+-[a-z0-9]*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"ENCAP") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST")) and not(contains(@tags, "IPSECHW"))]'
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-ethip4-pdrdisc \
-    --title "64B-1t1c-ethip4[a-z0-9]+-[a-z0-9]*-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"ENCAP") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"1T1C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST")) and not(contains(@tags, "IPSECHW"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-ethip4-pdrdisc \
-    --title "64B-2t2c-ethip4[a-z0-9]+-[a-z0-9]*-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"ENCAP") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"2T2C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST")) and not(contains(@tags, "IPSECHW"))]'
-
-# VPP IP6_overlay
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-1t1c-ethip6-ndrdisc \
-    --title "78B-1t1c-ethip6[a-z0-9]+-[a-z0-9]*-ndrdisc" \
-    --xpath '//*[@framesize="78B" and contains(@tags,"ENCAP") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-2t2c-ethip6-ndrdisc \
-    --title "78B-2t2c-ethip6[a-z0-9]+-[a-z0-9]*-ndrdisc" \
-    --xpath '//*[@framesize="78B" and contains(@tags,"ENCAP") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST"))]'
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-1t1c-ethip6-pdrdisc \
-    --title "78B-1t1c-ethip6[a-z0-9]+-[a-z0-9]*-pdrdisc" \
-    --xpath '//*[@framesize="78B" and contains(@tags,"ENCAP") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"1T1C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-2t2c-ethip6-pdrdisc \
-    --title "78B-2t2c-ethip6[a-z0-9]+-[a-z0-9]*-pdrdisc" \
-    --xpath '//*[@framesize="78B" and contains(@tags,"ENCAP") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"2T2C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST"))]'
-
-# VPP VM VHOST
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-vhost-sel1-ndrdisc \
-    --title "64B-1t1c-.*vhost.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"VHOST") and not(contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-vhost-sel1-ndrdisc \
-    --title "64B-2t2c-.*vhost.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"VHOST") and not(contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD"))]'
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-vhost-sel1-pdrdisc \
-    --title "64B-1t1c-.*vhost.*-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"PDRDISC") and contains(@tags,"1T1C") and not(contains(@tags,"NDRDISC")) and contains(@tags,"VHOST") and not(contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-vhost-sel1-pdrdisc \
-    --title "64B-2t2c-.*vhost.*-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"PDRDISC") and contains(@tags,"2T2C") and not(contains(@tags,"NDRDISC")) and contains(@tags,"VHOST") and not(contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD"))]'
-
-# VPP VM VHOST SELECTION
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-vhost-sel2-ndrdisc \
-    --title "64B-1t1c-.*vhost.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"VHOST") and not(contains(@tags,"VXLAN")) and not(contains(@tags,"IP4FWD")) and not(contains(@tags,"DOT1Q")) and not(contains(name(), "2Vm"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-vhost-sel2-ndrdisc \
-    --title "64B-2t2c-.*vhost.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"VHOST") and not(contains(@tags,"VXLAN")) and not(contains(@tags,"IP4FWD")) and not(contains(@tags,"DOT1Q")) and not(contains(name(), "2Vm"))]'
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-vhost-sel2-pdrdisc \
-    --title "64B-1t1c-.*vhost.*-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"PDRDISC") and contains(@tags,"1T1C") and not(contains(@tags,"NDRDISC")) and contains(@tags,"VHOST") and not(contains(@tags,"VXLAN")) and not(contains(@tags,"IP4FWD")) and not(contains(@tags,"DOT1Q")) and not(contains(name(), "2Vm"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-vhost-sel2-pdrdisc \
-    --title "64B-2t2c-.*vhost.*-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"PDRDISC") and contains(@tags,"2T2C") and not(contains(@tags,"NDRDISC")) and contains(@tags,"VHOST") and not(contains(@tags,"VXLAN")) and not(contains(@tags,"IP4FWD")) and not(contains(@tags,"DOT1Q")) and not(contains(name(), "2Vm"))]'
-
-# VPP CRYPTO
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-ipsechw-ndrdisc \
-    --title "64B-1t1c-.*ipsec.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and not(contains(@tags, "VHOST")) and contains(@tags, "IP4FWD") and contains(@tags, "NDRDISC") and contains(@tags, "1T1C") and contains(@tags, "IPSECHW") and (contains(@tags, "IPSECTRAN") or contains(@tags, "IPSECTUN"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-ipsechw-ndrdisc \
-    --title "64B-2t2c-.*ipsec.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and not(contains(@tags, "VHOST")) and contains(@tags, "IP4FWD") and contains(@tags, "NDRDISC") and contains(@tags, "2T2C") and contains(@tags, "IPSECHW") and (contains(@tags, "IPSECTRAN") or contains(@tags, "IPSECTUN"))]'
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-ipsechw-pdrdisc \
-    --title "64B-1t1c-.*ipsec.*-pdrdisc" \
-    --xpath '//*[@framesize="64B" and not(contains(@tags, "VHOST")) and contains(@tags, "IP4FWD") and contains(@tags, "PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags, "1T1C") and contains(@tags, "IPSECHW") and (contains(@tags, "IPSECTRAN") or contains(@tags, "IPSECTUN"))]'
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-ipsechw-pdrdisc \
-    --title "64B-2t2c-.*ipsec.*-pdrdisc" \
-    --xpath '//*[@framesize="64B" and not(contains(@tags, "VHOST")) and contains(@tags, "IP4FWD") and contains(@tags, "PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags, "2T2C") and contains(@tags, "IPSECHW") and (contains(@tags, "IPSECTRAN") or contains(@tags, "IPSECTUN"))]'
-
-# DPDK
-
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-1t1c-l2-ndrdisc \
-    --title "64B-1t1c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-2t2c-l2-ndrdisc \
-    --title "64B-2t2c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-1t1c-ipv4-ndrdisc \
-    --title "64B-1t1c-ethip4-ip4base-l3fwd-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"IP4FWD")]' \
-    --lower 2000000 --upper 12000000
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-2t2c-ipv4-ndrdisc \
-    --title "64B-2t2c-ethip4-ip4base-l3fwd-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"IP4FWD")]' \
-    --lower 2000000 --upper 12000000
-
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-1t1c-l2-pdrdisc \
-    --title "64B-1t1c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"1T1C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-2t2c-l2-pdrdisc \
-    --title "64B-2t2c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and not(contains(@tags,"NDRDISC")) and contains(@tags,"2T2C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]'
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-1t1c-ipv4-pdrdisc \
-    --title "64B-1t1c-ethip4-ip4base-l3fwd-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"1T1C") and contains(@tags,"IP4FWD")]' \
-    --lower 20000000 --upper 30000000
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-2t2c-ipv4-pdrdisc \
-    --title "64B-2t2c-ethip4-ip4base-l3fwd-pdrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"PDRDISC") and not(contains(@tags,"NDRDISC")) and contains(@tags,"2T2C") and contains(@tags,"IP4FWD")]' \
-    --lower 20000000 --upper 30000000
-
-# Plot latency
-
-# VPP L2 sel1
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-l2-sel1-ndrdisc-lat50 \
-    --title "64B-1t1c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-l2-sel1-ndrdisc-lat50 \
-    --title "64B-2t2c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-
-# VPP L2 sel2
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-l2-sel2-ndrdisc-lat50 \
-    --title "64B-1t1c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and ((contains(@tags,"FEATURE") and contains(@tags,"ACL50") and contains(@tags,"10k_FLOWS"))) and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-l2-sel2-ndrdisc-lat50 \
-    --title "64B-2t2c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and ((contains(@tags,"FEATURE") and contains(@tags,"ACL50") and contains(@tags,"10k_FLOWS"))) and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-
-# VPP IP4
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-ethip4-ip4-ndrdisc-lat50 \
-    --title "64B-1t1c-ethip4-ip4[a-z0-9]+-[a-z-]*ndrdisc" \
-    --xpath '//*[@framesize="64B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"IP4FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-ethip4-ip4-ndrdisc-lat50 \
-    --title "64B-2t2c-ethip4-ip4[a-z0-9]+-[a-z-]*ndrdisc" \
-    --xpath '//*[@framesize="64B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"IP4FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-
-# VPP IP6
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-1t1c-ethip6-ip6-ndrdisc-lat50 \
-    --title "78B-1t1c-ethip6-ip6[a-z0-9]+-[a-z-]*ndrdisc" \
-    --xpath '//*[@framesize="78B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"IP6FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-2t2c-ethip6-ip6-ndrdisc-lat50 \
-    --title "78B-2t2c-ethip6-ip6[a-z0-9]+-[a-z-]*ndrdisc" \
-    --xpath '//*[@framesize="78B" and (contains(@tags,"BASE") or contains(@tags,"SCALE") or contains(@tags,"FEATURE")) and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"IP6FWD") and not(contains(@tags,"IPSEC")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-
-# VPP IP4_overlay
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-ethip4-ndrdisc-lat50 \
-    --title "64B-1t1c-ethip4[a-z0-9]+-[a-z0-9]*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"ENCAP") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST")) and not(contains(@tags, "IPSECHW"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-ethip4-ndrdisc-lat50 \
-    --title "64B-2t2c-ethip4[a-z0-9]+-[a-z0-9]*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"ENCAP") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST")) and not(contains(@tags, "IPSECHW"))]' --latency lat_50
-
-# VPP IP6_overlay
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-1t1c-ethip6-ndrdisc-lat50 \
-    --title "78B-1t1c-ethip6[a-z0-9]+-[a-z0-9]*-ndrdisc" \
-    --xpath '//*[@framesize="78B" and contains(@tags,"ENCAP") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/78B-2t2c-ethip6-ndrdisc-lat50 \
-    --title "78B-2t2c-ethip6[a-z0-9]+-[a-z0-9]*-ndrdisc" \
-    --xpath '//*[@framesize="78B" and contains(@tags,"ENCAP") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"VXLAN") or contains(@tags,"VXLANGPE") or contains(@tags,"LISP") or contains(@tags,"LISPGPE") or contains(@tags,"GRE")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-
-# VPP VM VHOST
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-vhost-sel1-ndrdisc-lat50 \
-    --title "64B-1t1c-.*vhost.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"VHOST") and not(contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-vhost-sel1-ndrdisc-lat50 \
-    --title "64B-2t2c-.*vhost.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"VHOST") and not(contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD"))]' --latency lat_50
-
-# VPP VM VHOST selection
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-vhost-sel2-ndrdisc-lat50 \
-    --title "64B-1t1c-.*vhost.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"VHOST") and not(contains(@tags,"VXLAN")) and not(contains(@tags,"IP4FWD")) and not(contains(@tags,"DOT1Q")) and not(contains(name(), "2Vm"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-vhost-sel2-ndrdisc-lat50 \
-    --title "64B-2t2c-.*vhost.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"VHOST") and not(contains(@tags,"VXLAN")) and not(contains(@tags,"IP4FWD")) and not(contains(@tags,"DOT1Q")) and not(contains(name(), "2Vm"))]' --latency lat_50
-
-# VPP CRYPTO
-
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-1t1c-ipsechw-ndrdisc-lat50 \
-    --title "64B-1t1c-.*ipsec.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and not(contains(@tags, "VHOST")) and contains(@tags, "IP4FWD") and contains(@tags, "NDRDISC") and contains(@tags, "1T1C") and contains(@tags, "IPSECHW") and (contains(@tags, "IPSECTRAN") or contains(@tags, "IPSECTUN"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,VPP]} \
-    --output ${DIR[STATIC,VPP]}/64B-2t2c-ipsechw-ndrdisc-lat50 \
-    --title "64B-2t2c-.*ipsec.*-ndrdisc" \
-    --xpath '//*[@framesize="64B" and not(contains(@tags, "VHOST")) and contains(@tags, "IP4FWD") and contains(@tags, "NDRDISC") and contains(@tags, "2T2C") and contains(@tags, "IPSECHW") and (contains(@tags, "IPSECTRAN") or contains(@tags, "IPSECTUN"))]' --latency lat_50
-
-# DPDK
-
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-1t1c-l2-ndrdisc-lat50 \
-    --title "64B-1t1c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-2t2c-l2-ndrdisc-lat50 \
-    --title "64B-2t2c-(eth|dot1q|dot1ad)-(l2xcbase|l2bdbasemaclrn)-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and (contains(@tags,"L2BDMACSTAT") or contains(@tags,"L2BDMACLRN") or contains(@tags,"L2XCFWD")) and not(contains(@tags,"VHOST"))]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-1t1c-ipv4-ndrdisc-lat50 \
-    --title "64B-1t1c-ethip4-ip4base-l3fwd-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"1T1C") and contains(@tags,"IP4FWD")]' --latency lat_50
-python run_plot.py --input ${DIR[PLOT,DPDK]} \
-    --output ${DIR[STATIC,DPDK]}/64B-2t2c-ipv4-ndrdisc-lat50 \
-    --title "64B-2t2c-ethip4-ip4base-l3fwd-ndrdisc" \
-    --xpath '//*[@framesize="64B" and contains(@tags,"BASE") and contains(@tags,"NDRDISC") and contains(@tags,"2T2C") and contains(@tags,"IP4FWD")]' --latency lat_50
-
-# HTML BUILDER
-if [[ ${CFG[BLD_HTML]} -eq 1 ]] ;
-then
-    sphinx-build -v -c . -a -b html -E \
-        -D release=$1 -D version="$1 report - $DATE" \
-        ${DIR[RST]} ${DIR[BUILD,HTML]}/
-
-    # Patch the CSS for tables layout
-    cat - > ${DIR[CSS_PATCH_FILE]} <<"_EOF"
-/* override table width restrictions */
-@media screen and (min-width: 767px) {
-    .wy-table-responsive table td, .wy-table-responsive table th {
-        white-space: normal !important;
-    }
-
-    .wy-table-responsive {
-        font-size: small;
-        margin-bottom: 24px;
-        max-width: 100%;
-        overflow: visible !important;
-    }
-}
-_EOF
-fi
-
-# LATEX BUILDER
-if [[ ${CFG[BLD_LATEX]} -eq 1 ]] ;
-then
-    # Convert PyPLOT graphs in HTML format to PDF.
-    for f in ${DIR[STATIC,VPP]}/*; do
-        xvfb-run -a wkhtmltopdf ${f} ${f%.html}.pdf
-    done
-    for f in ${DIR[STATIC,DPDK]}/*; do
-        xvfb-run -a wkhtmltopdf ${f} ${f%.html}.pdf
-    done
-
-    # Generate the LaTeX documentation
-    sphinx-build -v -c . -a -b latex -E \
-        -D release=$1 -D version="$1 report - $DATE" \
-        ${DIR[RST]} ${DIR[BUILD,LATEX]}
-    cd ${DIR[BUILD,LATEX]}
-    pdflatex -shell-escape -interaction nonstopmode csit.tex || true
-    pdflatex -interaction nonstopmode csit.tex || true
-    cp csit.pdf ../${DIR[STATIC,ARCH]}/csit_$1.pdf
-    cd ${SCRIPT_DIR}
-fi
-
-# Create archive
-echo Creating csit.report.tar.gz ...
-tar -czvf ./csit.report.tar.gz ${DIR[BUILD,HTML]}
diff --git a/resources/tools/report_gen/run_robot_data.py b/resources/tools/report_gen/run_robot_data.py
deleted file mode 100755 (executable)
index d5672b4..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2017 Cisco and/or its affiliates.
-# 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.
-
-"""
-Script extracts interested data (name, documentation, message, status) from
-robot framework output file (output.xml) and prints in specified format (wiki,
-html, rst) to defined output file.
-
-Supported formats:
- - html
- - rst
- - wiki
-
-:TODO:
- - md
-
-:Example:
-
-run_robot_data.py -i "output.xml" -o "tests.rst" -f "rst" -s 3 -l 2
-
-The example reads the data from "output.xml", writes the output to "tests.rst"
-in rst format. It will start on the 3rd level of xml structure and the generated
-document hierarchy will start on the 2nd level.
-All test suites will be processed.
-
-:Example:
-
-run_robot_data.py -i "output.xml" -o "tests.rst" -f "rst" -r "(.*)(lisp)(.*)"
-
-The example reads the data from "output.xml", writes the output to "tests.rst"
-in rst format. It will start on the 1st level of xml structure and the generated
-document hierarchy will start on the 1st level (default values).
-Only the test suites which match the given regular expression are processed.
-"""
-
-import argparse
-import re
-import sys
-import json
-import string
-
-from robot.api import ExecutionResult, ResultVisitor
-
-
-class ExecutionChecker(ResultVisitor):
-    """Class to traverse through the test suite structure.
-
-    The functionality implemented in this class generates a json file. Its
-    structure is:
-
-    [
-        {
-            "level": "Level of the suite, type: str",
-            "title": "Title of the suite, type: str",
-            "doc": "Documentation of the suite, type: str",
-            "table": [
-                ["TC name", "TC doc", "message or status"],
-                ["TC name", "TC doc", "message or status"],
-                ... other test cases ...
-                ["Name", "Documentation", "Message or Status"]
-            ]
-        },
-        ... other test suites ...
-    ]
-
-    .. note:: The header of the table with TCs is at the and of the table.
-    """
-
-    def __init__(self, args):
-        self.formatting = args.formatting
-
-    def visit_suite(self, suite):
-        """Implements traversing through the suite and its direct children.
-
-        :param suite: Suite to process.
-        :type suite: Suite
-        :returns: Nothing.
-        """
-
-        if self.start_suite(suite) is not False:
-            if suite.tests:
-                sys.stdout.write(',"tests":[')
-            else:
-                sys.stdout.write('},')
-
-            suite.suites.visit(self)
-            suite.tests.visit(self)
-
-            if suite.tests:
-                if "ndrdisc" in suite.longname.lower():
-                    hdr = '["Name","Documentation","Message"]'
-                else:
-                    hdr = '["Name","Documentation","Status"]'
-                sys.stdout.write(hdr + ']},')
-
-            self.end_suite(suite)
-
-    def start_suite(self, suite):
-        """Called when suite starts.
-
-        :param suite: Suite to process.
-        :type suite: Suite
-        :returns: Nothing.
-        """
-
-        level = len(suite.longname.split("."))
-        sys.stdout.write('{')
-        sys.stdout.write('"level":"' + str(level) + '",')
-        sys.stdout.write('"title":"' + suite.name.replace('"', "'") + '",')
-        sys.stdout.write('"doc":"' + suite.doc.replace('"', "'").
-                         replace('\n', ' ').replace('\r', '').
-                         replace('*[', ' |br| *[') + '"')
-
-    def end_suite(self, suite):
-        """Called when suite ends.
-
-        :param suite: Suite to process.
-        :type suite: Suite
-        :returns: Nothing.
-        """
-        pass
-
-    def visit_test(self, test):
-        """Implements traversing through the test.
-
-        :param test: Test to process.
-        :type test: Test
-        :returns: Nothing.
-        """
-        if self.start_test(test) is not False:
-            self.end_test(test)
-
-    def start_test(self, test):
-        """Called when test starts.
-
-        :param test: Test to process.
-        :type test: Test
-        :returns: Nothing.
-        """
-
-        name = test.name.replace('"', "'")
-        doc = test.doc.replace('"', "'").replace('\n', ' ').replace('\r', '').\
-            replace('[', ' |br| [')
-        if any("NDRPDRDISC" in tag for tag in test.tags):
-            msg = test.message.replace('\n', ' |br| ').replace('\r', ''). \
-                replace('"', "'")
-
-            sys.stdout.write('["' + name + '","' + doc + '","' + msg + '"]')
-        else:
-            sys.stdout.write(
-                '["' + name + '","' + doc + '","' + test.status + '"]')
-
-    def end_test(self, test):
-        """Called when test ends.
-
-        :param test: Test to process.
-        :type test: Test
-        :returns: Nothing.
-        """
-        sys.stdout.write(',')
-
-
-def do_html(data, args):
-    """Generation of a html file from json data.
-
-    :param data: List of suites from json file.
-    :param args: Parsed arguments.
-    :type data: list of dict
-    :type args: ArgumentParser
-    :returns: Nothing.
-    """
-
-    shift = int(args.level)
-    start = int(args.start)
-
-    output = open(args.output, 'w')
-
-    output.write('<html>')
-    for item in data:
-        if int(item['level']) < start:
-            continue
-        level = str(int(item['level']) - start + shift)
-        output.write('<h' + level + '>' + item['title'].lower() +
-                     '</h' + level + '>')
-        output.write('<p>' + re.sub(r"(\*)(.*?)(\*)", r"<b>\2</b>", item['doc'],
-                                    0, flags=re.MULTILINE).
-                     replace(' |br| ', '<br>') + '</p>')
-        try:
-            output.write(gen_html_table(item['tests']))
-        except KeyError:
-            continue
-    output.write('</html>')
-    output.close()
-
-
-def gen_html_table(data):
-    """Generates a table with TCs' names, documentation and messages / statuses
-    in html format. There is no css used.
-
-    :param data: Json data representing a table with TCs.
-    :type data: str
-    :returns: Table with TCs' names, documentation and messages / statuses in
-    html format.
-    :rtype: str
-    """
-
-    table = '<table width=100% border=1><tr>'
-    table += '<th width=30%>' + data[-1][0] + '</th>'
-    table += '<th width=50%>' + data[-1][1] + '</th>'
-    table += '<th width=20%>' + data[-1][2] + '</th></tr>'
-
-    for item in data[0:-1]:
-        table += '<tr>'
-        for element in item:
-            table += '<td>' + element.replace(' |br| ', '<br>') + '</td>'
-    table += '</tr></table>'
-
-    return table
-
-
-def do_rst(data, args):
-    """Generation of a rst file from json data.
-
-    :param data: List of suites from json file.
-    :param args: Parsed arguments.
-    :type data: list of dict
-    :type args: ArgumentParser
-    :returns: Nothing.
-    """
-
-    hdrs = ['=', '-', '`', "'", '.', '~', '*', '+', '^']
-    shift = int(args.level)
-    start = int(args.start)
-
-    output = open(args.output, 'w')
-    output.write('\n.. |br| raw:: html\n\n    <br />\n\n')
-
-    if (args.title):
-        output.write(args.title + '\n' +
-                     hdrs[shift - 1] *
-                     len(args.title) + '\n\n')
-
-    for item in data:
-        if int(item['level']) < start:
-            continue
-        if 'ndrchk' in item['title'].lower():
-            continue
-        output.write(item['title'].lower() + '\n' +
-                     hdrs[int(item['level']) - start + shift] *
-                     len(item['title']) + '\n\n')
-        output.write(item['doc'].replace('*', '**').replace('|br|', '\n\n -') +
-                     '\n\n')
-        try:
-            output.write(gen_rst_table(item['tests']) + '\n\n')
-        except KeyError:
-            continue
-    output.close()
-
-
-def gen_rst_table(data):
-    """Generates a table with TCs' names, documentation and messages / statuses
-    in rst format.
-
-    :param data: Json data representing a table with TCs.
-    :type data: str
-    :returns: Table with TCs' names, documentation and messages / statuses in
-    rst format.
-    :rtype: str
-    """
-
-    table = []
-    # max size of each column
-    lengths = map(max, zip(*[[len(str(elt)) for elt in item] for item in data]))
-
-    start_of_line = '| '
-    vert_separator = ' | '
-    end_of_line = ' |'
-    line_marker = '-'
-
-    meta_template = vert_separator.join(['{{{{{0}:{{{0}}}}}}}'.format(i)
-                                         for i in range(len(lengths))])
-    template = '{0}{1}{2}'.format(start_of_line, meta_template.format(*lengths),
-                                  end_of_line)
-    # determine top/bottom borders
-    to_separator = string.maketrans('| ', '+-')
-    start_of_line = start_of_line.translate(to_separator)
-    vert_separator = vert_separator.translate(to_separator)
-    end_of_line = end_of_line.translate(to_separator)
-    separator = '{0}{1}{2}'.format(start_of_line, vert_separator.
-                                   join([x * line_marker for x in lengths]),
-                                   end_of_line)
-    # determine header separator
-    th_separator_tr = string.maketrans('-', '=')
-    start_of_line = start_of_line.translate(th_separator_tr)
-    line_marker = line_marker.translate(th_separator_tr)
-    vertical_separator = vert_separator.translate(th_separator_tr)
-    end_of_line = end_of_line.translate(th_separator_tr)
-    th_separator = '{0}{1}{2}'.format(start_of_line, vertical_separator.
-                                      join([x * line_marker for x in lengths]),
-                                      end_of_line)
-    # prepare table
-    table.append(separator)
-    # set table header
-    titles = data[-1]
-    table.append(template.format(*titles))
-    table.append(th_separator)
-    # generate table rows
-    for item in data[0:-2]:
-        desc = re.sub(r'(^ \|br\| )', r'', item[1])
-        table.append(template.format(item[0], desc, item[2]))
-        table.append(separator)
-    desc = re.sub(r'(^ \|br\| )', r'', data[-2][1])
-    table.append(template.format(data[-2][0], desc, data[-2][2]))
-    table.append(separator)
-    return '\n'.join(table)
-
-
-def do_md(data, args):
-    """Generation of a rst file from json data.
-
-    :param data: List of suites from json file.
-    :param args: Parsed arguments.
-    :type data: list of dict
-    :type args: ArgumentParser
-    :returns: Nothing.
-    """
-    raise NotImplementedError("Export to 'md' format is not implemented.")
-
-
-def do_wiki(data, args):
-    """Generation of a wiki page from json data.
-
-    :param data: List of suites from json file.
-    :param args: Parsed arguments.
-    :type data: list of dict
-    :type args: ArgumentParser
-    :returns: Nothing.
-    """
-
-    shift = int(args.level)
-    start = int(args.start)
-
-    output = open(args.output, 'w')
-
-    for item in data:
-        if int(item['level']) < start:
-            continue
-        if 'ndrchk' in item['title'].lower():
-            continue
-        mark = "=" * (int(item['level']) - start + shift) + ' '
-        output.write(mark + item['title'].lower() + mark + '\n')
-        output.write(item['doc'].replace('*', "'''").replace('|br|', '\n*') +
-                     '\n')
-        try:
-            output.write(gen_wiki_table(item['tests']) + '\n\n')
-        except KeyError:
-            continue
-    output.close()
-
-
-def gen_wiki_table(data):
-    """Generates a table with TCs' names, documentation and messages / statuses
-    in wiki format.
-
-    :param data: Json data representing a table with TCs.
-    :type data: str
-    :returns: Table with TCs' names, documentation and messages / statuses in
-    wiki format.
-    :rtype: str
-    """
-
-    table = '{| class="wikitable"\n'
-    header = ""
-    for item in data[-1]:
-        header += '!{}\n'.format(item)
-    table += header
-    for item in data[0:-1]:
-        desc = re.sub(r'(^ \|br\| )', r'', item[1]).replace(' |br| ', '\n\n')
-        msg = item[2].replace(' |br| ', '\n\n')
-        table += '|-\n|{}\n|{}\n|{}\n'.format(item[0], desc, msg)
-    table += '|}\n'
-
-    return table
-
-
-def process_robot_file(args):
-    """Process data from robot output.xml file and generate defined file type.
-
-    :param args: Parsed arguments.
-    :type args: ArgumentParser
-    :return: Nothing.
-    """
-
-    old_sys_stdout = sys.stdout
-    sys.stdout = open(args.output + '.json', 'w')
-
-    result = ExecutionResult(args.input)
-    checker = ExecutionChecker(args)
-
-    sys.stdout.write('[')
-    result.visit(checker)
-    sys.stdout.write('{}]')
-    sys.stdout.close()
-    sys.stdout = old_sys_stdout
-
-    with open(args.output + '.json', 'r') as json_file:
-        data = json.load(json_file)
-    data.pop(-1)
-
-    if args.regex:
-        results = list()
-        regex = re.compile(args.regex)
-        for item in data:
-            if re.search(regex, item['title'].lower()):
-                results.append(item)
-    else:
-        results = data
-
-    if args.formatting == 'rst':
-        do_rst(results, args)
-    elif args.formatting == 'wiki':
-        do_wiki(results, args)
-    elif args.formatting == 'html':
-        do_html(results, args)
-    elif args.formatting == 'md':
-        do_md(results, args)
-
-
-def parse_args():
-    """Parse arguments from cmd line.
-
-    :return: Parsed arguments.
-    :rtype ArgumentParser
-    """
-
-    parser = argparse.ArgumentParser(description=__doc__,
-                                     formatter_class=argparse.
-                                     RawDescriptionHelpFormatter)
-    parser.add_argument("-i", "--input",
-                        required=True,
-                        type=argparse.FileType('r'),
-                        help="Robot XML log file")
-    parser.add_argument("-o", "--output",
-                        type=str,
-                        required=True,
-                        help="Output file")
-    parser.add_argument("-f", "--formatting",
-                        required=True,
-                        choices=['html', 'wiki', 'rst', 'md'],
-                        help="Output file format")
-    parser.add_argument("-s", "--start",
-                        type=int,
-                        default=1,
-                        help="The first level to be taken from xml file")
-    parser.add_argument("-l", "--level",
-                        type=int,
-                        default=1,
-                        help="The level of the first chapter in generated file")
-    parser.add_argument("-r", "--regex",
-                        type=str,
-                        default=None,
-                        help="Regular expression used to select test suites. "
-                             "If None, all test suites are selected.")
-    parser.add_argument("-t", "--title",
-                        type=str,
-                        default=None,
-                        help="Title of the output.")
-
-    return parser.parse_args()
-
-
-if __name__ == "__main__":
-    sys.exit(process_robot_file(parse_args()))
diff --git a/resources/tools/report_gen/run_robot_json_data.py b/resources/tools/report_gen/run_robot_json_data.py
deleted file mode 100755 (executable)
index 708836a..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2017 Cisco and/or its affiliates.
-# 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.
-
-"""
-Script extracts required data from robot framework output file (output.xml) and
-saves it in JSON format. Its structure is:
-
-{
-    "metadata": {
-        "vdevice": "VPP version",
-        "data-length": int
-    },
-    "data": {
-        "ID": {
-            "name": "Test name",
-            "parent": "Name of the parent of the test",
-            "tags": ["tag 1", "tag 2", "tag n"],
-            "type": "PDR" | "NDR",
-            "throughput": {
-                "value": int,
-                "unit": "pps" | "bps" | "percentage"
-            },
-            "latency": {
-                "direction1": {
-                    "100": {
-                        "min": int,
-                        "avg": int,
-                        "max": int
-                    },
-                    "50": {  # Only for NDR
-                        "min": int,
-                        "avg": int,
-                        "max": int
-                    },
-                    "10": {  # Only for NDR
-                        "min": int,
-                        "avg": int,
-                        "max": int
-                    }
-                },
-                "direction2": {
-                    "100": {
-                        "min": int,
-                        "avg": int,
-                        "max": int
-                    },
-                    "50": {  # Only for NDR
-                        "min": int,
-                        "avg": int,
-                        "max": int
-                    },
-                    "10": {  # Only for NDR
-                        "min": int,
-                        "avg": int,
-                        "max": int
-                    }
-                }
-            },
-            "lossTolerance": "lossTolerance"  # Only for PDR
-        },
-        "ID" {
-            # next test
-        }
-    }
-}
-
-.. note:: ID is the lowercase full path to the test.
-
-:Example:
-
-run_robot_json_data.py -i "output.xml" -o "data.json" -v "17.07-rc0~144"
-
-"""
-
-import argparse
-import re
-import sys
-import json
-
-from robot.api import ExecutionResult, ResultVisitor
-
-
-class ExecutionChecker(ResultVisitor):
-    """Class to traverse through the test suite structure.
-
-    The functionality implemented in this class generates a json structure.
-    """
-
-    REGEX_RATE = re.compile(r'^[\D\d]*FINAL_RATE:\s(\d+\.\d+)\s(\w+)')
-
-    REGEX_LAT_NDR = re.compile(r'^[\D\d]*'
-                               r'LAT_\d+%NDR:\s\[\'(-?\d+\/-?\d+\/-?\d+)\','
-                               r'\s\'(-?\d+\/-?\d+\/-?\d+)\'\]\s\n'
-                               r'LAT_\d+%NDR:\s\[\'(-?\d+\/-?\d+\/-?\d+)\','
-                               r'\s\'(-?\d+\/-?\d+\/-?\d+)\'\]\s\n'
-                               r'LAT_\d+%NDR:\s\[\'(-?\d+\/-?\d+\/-?\d+)\','
-                               r'\s\'(-?\d+\/-?\d+\/-?\d+)\'\]')
-
-    REGEX_LAT_PDR = re.compile(r'^[\D\d]*'
-                               r'LAT_\d+%PDR:\s\[\'(-?\d+\/-?\d+\/-?\d+)\','
-                               r'\s\'(-?\d+\/-?\d+\/-?\d+)\'\][\D\d]*')
-
-    REGEX_TOLERANCE = re.compile(r'^[\D\d]*LOSS_ACCEPTANCE:\s(\d*\.\d*)\s'
-                                 r'[\D\d]*')
-
-    def __init__(self, **metadata):
-        """Initialisation.
-
-        :param metadata: Key-value pairs to be included to "metadata" part of
-        JSON structure.
-        :type metadata: dict
-        """
-        self._data = {
-            "metadata": {
-            },
-            "data": {
-            }
-        }
-
-        for key, val in metadata.items():
-            self._data["metadata"][key] = val
-
-    @property
-    def data(self):
-        return self._data
-
-    def _get_latency(self, msg, test_type):
-        """Get the latency data from the test message.
-
-        :param msg: Message to be parsed.
-        :param test_type: Type of the test - NDR or PDR.
-        :type msg: str
-        :type test_type: str
-        :returns: Latencies parsed from the message.
-        :rtype: dict
-        """
-
-        if test_type == "NDR":
-            groups = re.search(self.REGEX_LAT_NDR, msg)
-            groups_range = range(1, 7)
-        elif test_type == "PDR":
-            groups = re.search(self.REGEX_LAT_PDR, msg)
-            groups_range = range(1, 3)
-        else:
-            return {}
-
-        latencies = list()
-        for idx in groups_range:
-            try:
-                lat = [int(item) for item in str(groups.group(idx)).split('/')]
-            except (AttributeError, ValueError):
-                lat = [-1, -1, -1]
-            latencies.append(lat)
-
-        keys = ("min", "avg", "max")
-        latency = {
-            "direction1": {
-            },
-            "direction2": {
-            }
-        }
-
-        latency["direction1"]["100"] = dict(zip(keys, latencies[0]))
-        latency["direction2"]["100"] = dict(zip(keys, latencies[1]))
-        if test_type == "NDR":
-            latency["direction1"]["50"] = dict(zip(keys, latencies[2]))
-            latency["direction2"]["50"] = dict(zip(keys, latencies[3]))
-            latency["direction1"]["10"] = dict(zip(keys, latencies[4]))
-            latency["direction2"]["10"] = dict(zip(keys, latencies[5]))
-
-        return latency
-
-    def visit_suite(self, suite):
-        """Implements traversing through the suite and its direct children.
-
-        :param suite: Suite to process.
-        :type suite: Suite
-        :returns: Nothing.
-        """
-        if self.start_suite(suite) is not False:
-            suite.suites.visit(self)
-            suite.tests.visit(self)
-            self.end_suite(suite)
-
-    def start_suite(self, suite):
-        """Called when suite starts.
-
-        :param suite: Suite to process.
-        :type suite: Suite
-        :returns: Nothing.
-        """
-        pass
-
-    def end_suite(self, suite):
-        """Called when suite ends.
-
-        :param suite: Suite to process.
-        :type suite: Suite
-        :returns: Nothing.
-        """
-        pass
-
-    def visit_test(self, test):
-        """Implements traversing through the test.
-
-        :param test: Test to process.
-        :type test: Test
-        :returns: Nothing.
-        """
-        if self.start_test(test) is not False:
-            self.end_test(test)
-
-    def start_test(self, test):
-        """Called when test starts.
-
-        :param test: Test to process.
-        :type test: Test
-        :returns: Nothing.
-        """
-
-        tags = [str(tag) for tag in test.tags]
-        if test.status == "PASS" and "NDRPDRDISC" in tags:
-
-            if "NDRDISC" in tags:
-                test_type = "NDR"
-            elif "PDRDISC" in tags:
-                test_type = "PDR"
-            else:
-                return
-
-            try:
-                rate_value = str(re.search(
-                    self.REGEX_RATE, test.message).group(1))
-            except AttributeError:
-                rate_value = "-1"
-            try:
-                rate_unit = str(re.search(
-                    self.REGEX_RATE, test.message).group(2))
-            except AttributeError:
-                rate_unit = "-1"
-
-            test_result = dict()
-            test_result["name"] = test.name.lower()
-            test_result["parent"] = test.parent.name.lower()
-            test_result["tags"] = tags
-            test_result["type"] = test_type
-            test_result["throughput"] = dict()
-            test_result["throughput"]["value"] = int(rate_value.split('.')[0])
-            test_result["throughput"]["unit"] = rate_unit
-            test_result["latency"] = self._get_latency(test.message, test_type)
-            if test_type == "PDR":
-                test_result["lossTolerance"] = str(re.search(
-                    self.REGEX_TOLERANCE, test.message).group(1))
-
-            self._data["data"][test.longname.lower()] = test_result
-
-    def end_test(self, test):
-        """Called when test ends.
-
-        :param test: Test to process.
-        :type test: Test
-        :returns: Nothing.
-        """
-        pass
-
-
-def parse_tests(args):
-    """Process data from robot output.xml file and return JSON data.
-
-    :param args: Parsed arguments.
-    :type args: ArgumentParser
-    :returns: JSON data structure.
-    :rtype: dict
-    """
-
-    result = ExecutionResult(args.input)
-    checker = ExecutionChecker(vdevice=args.vdevice)
-    result.visit(checker)
-
-    return checker.data
-
-
-def parse_args():
-    """Parse arguments from cmd line.
-
-    :returns: Parsed arguments.
-    :rtype: ArgumentParser
-    """
-
-    parser = argparse.ArgumentParser(description=__doc__,
-                                     formatter_class=argparse.
-                                     RawDescriptionHelpFormatter)
-    parser.add_argument("-i", "--input",
-                        required=True,
-                        type=argparse.FileType('r'),
-                        help="Robot XML log file.")
-    parser.add_argument("-o", "--output",
-                        required=True,
-                        type=argparse.FileType('w'),
-                        help="JSON output file")
-    parser.add_argument("-v", "--vdevice",
-                        required=False,
-                        default="",
-                        type=str,
-                        help="VPP version")
-
-    return parser.parse_args()
-
-
-def main():
-    """Main function."""
-
-    args = parse_args()
-    json_data = parse_tests(args)
-    json_data["metadata"]["data-length"] = len(json_data["data"])
-    json.dump(json_data, args.output)
-
-if __name__ == "__main__":
-    sys.exit(main())
diff --git a/resources/tools/report_gen/run_robot_teardown_data.py b/resources/tools/report_gen/run_robot_teardown_data.py
deleted file mode 100755 (executable)
index df2aae5..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2017 Cisco and/or its affiliates.
-# 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.
-
-"""
-Script extracts interested data (name, VAT command history or table from Show
-Runtime command) from robot framework output file (output.xml) and prints in
-specified format (wiki, html, rst) to defined output file.
-
-Supported formats:
- - html
- - rst
- - wiki
-
-:TODO:
- - md
-
-:Example:
-
-run_robot_teardown_data.py -i "output.xml" -o "tests.rst" -d "VAT_H" -f "rst"
--s 3 -l 2
-
-The example reads the VAT command history data from "output.xml", writes
-the output to "tests.rst" in rst format. It will start on the 3rd level of xml
-structure and the generated document hierarchy will start on the 2nd level.
-
-:Example:
-
-run_robot_teardown_data.py -i "output.xml" -o "tests.rst" -f "rst" -d "SH_RUN"
- -r "(.*)(lisp)(.*)"
-
-The example reads the data from "output.xml", writes the output to "tests.rst"
-in rst format. It will start on the 1st level of xml structure and the generated
-document hierarchy will start on the 1st level (default values).
-Only the test suites which match the given regular expression are processed.
-"""
-
-import argparse
-import re
-import sys
-import json
-import string
-
-from robot.api import ExecutionResult, ResultVisitor
-
-
-class ExecutionChecker(ResultVisitor):
-    """Class to traverse through the test suite structure.
-
-    The functionality implemented in this class generates a json file. Its
-    structure is:
-
-    [
-        {
-            "level": "Level of the suite, type: str",
-            "title": "Title of the suite, type: str",
-            "doc": "Documentation of the suite, type: str",
-            "table": [
-                ["TC name", "VAT history or show runtime"],
-                ["TC name", "VAT history or show runtime"],
-                ... other test cases ...
-                ["Name","VAT command history or VPP operational data"]
-            ]
-        },
-        ... other test suites ...
-    ]
-
-    .. note:: The header of the table with TCs is at the end of the table.
-    """
-
-    def __init__(self, args):
-        self.formatting = args.formatting
-        self.data = args.data
-        self.tagin = " |prein| "
-        self.tagout = " |preout| "
-        if self.data == "VAT_H":
-            self.lookup_kw = "Show Vat History On All Duts"
-            self.column_name = "VPP API Test (VAT) Commands History - " \
-                               "Commands Used Per Test Case"
-        elif self.data == "SH_RUN":
-            self.lookup_kw = "Vpp Show Runtime"
-            self.column_name = "VPP Operational Data - Outputs of " \
-                               "'show runtime' at NDR packet rate"
-        else:
-            raise ValueError("{0} look-up not implemented.".format(self.data))
-        self.lookup_kw_nr = 0
-        self.lookup_msg_nr = 0
-
-    def visit_suite(self, suite):
-        """Implements traversing through the suite and its direct children.
-
-        :param suite: Suite to process.
-        :type suite: Suite
-        :returns: Nothing.
-        """
-
-        if self.start_suite(suite) is not False:
-            if suite.tests:
-                sys.stdout.write(',"tests":[')
-            else:
-                sys.stdout.write('},')
-
-            suite.suites.visit(self)
-            suite.tests.visit(self)
-
-            if suite.tests:
-                hdr = '["Name","' + self.column_name + '"]'
-                sys.stdout.write(hdr + ']},')
-
-            self.end_suite(suite)
-
-    def start_suite(self, suite):
-        """Called when suite starts.
-
-        :param suite: Suite to process.
-        :type suite: Suite
-        :returns: Nothing.
-        """
-
-        level = len(suite.longname.split("."))
-        sys.stdout.write('{')
-        sys.stdout.write('"level":"' + str(level) + '",')
-        sys.stdout.write('"title":"' + suite.name.replace('"', "'") + '",')
-        sys.stdout.write('"doc":"' + suite.doc.replace('"', "'").
-                         replace('\n', ' ').replace('\r', '').
-                         replace('*[', ' |br| *[') + '"')
-
-    def end_suite(self, suite):
-        """Called when suite ends.
-
-        :param suite: Suite to process.
-        :type suite: Suite
-        :returns: Nothing.
-        """
-        pass
-
-    def visit_test(self, test):
-        """Implements traversing through the test.
-
-        :param test: Test to process.
-        :type test: Test
-        :returns: Nothing.
-        """
-        if self.start_test(test) is not False:
-            test.keywords.visit(self)
-            self.end_test(test)
-
-    def start_test(self, test):
-        """Called when test starts.
-
-        :param test: Test to process.
-        :type test: Test
-        :returns: Nothing.
-        """
-
-        name = test.name.replace('"', "'")
-        sys.stdout.write('["' + name + '","' + self.tagin)
-
-    def end_test(self, test):
-        """Called when test ends.
-
-        :param test: Test to process.
-        :type test: Test
-        :returns: Nothing.
-        """
-        sys.stdout.write(self.tagout + '"],')
-
-    def visit_keyword(self, kw):
-        """Implements traversing through the keyword and its child keywords.
-
-        :param kw: Keyword to process.
-        :type kw: Keyword
-        :returns: Nothing.
-        """
-        if self.start_keyword(kw) is not False:
-            self.end_keyword(kw)
-
-    def start_keyword(self, kw):
-        """Called when keyword starts. Default implementation does nothing.
-
-        :param kw: Keyword to process.
-        :type kw: Keyword
-        :returns: Nothing.
-        """
-        try:
-            if kw.type == "teardown":
-                self.lookup_kw_nr = 0
-                self.visit_teardown_kw(kw)
-        except AttributeError:
-            pass
-
-    def end_keyword(self, kw):
-        """Called when keyword ends. Default implementation does nothing.
-
-        :param kw: Keyword to process.
-        :type kw: Keyword
-        :returns: Nothing.
-        """
-        pass
-
-    def visit_teardown_kw(self, kw):
-        """Implements traversing through the teardown keyword and its child
-        keywords.
-
-        :param kw: Keyword to process.
-        :type kw: Keyword
-        :returns: Nothing.
-        """
-        for keyword in kw.keywords:
-            if self.start_teardown_kw(keyword) is not False:
-                self.visit_teardown_kw(keyword)
-                self.end_teardown_kw(keyword)
-
-    def start_teardown_kw(self, kw):
-        """Called when teardown keyword starts. Default implementation does
-        nothing.
-
-        :param kw: Keyword to process.
-        :type kw: Keyword
-        :returns: Nothing.
-        """
-        if kw.name.count(self.lookup_kw):
-            self.lookup_kw_nr += 1
-            self.lookup_msg_nr = 0
-            kw.messages.visit(self)
-
-    def end_teardown_kw(self, kw):
-        """Called when keyword ends. Default implementation does nothing.
-
-        :param kw: Keyword to process.
-        :type kw: Keyword
-        :returns: Nothing.
-        """
-        pass
-
-    def visit_message(self, msg):
-        """Implements visiting the message.
-
-        :param msg: Message to process.
-        :type msg: Message
-        :returns: Nothing.
-        """
-        if self.start_message(msg) is not False:
-            self.end_message(msg)
-
-    def start_message(self, msg):
-        """Called when message starts. Default implementation does nothing.
-
-        :param msg: Message to process.
-        :type msg: Message
-        :returns: Nothing.
-        """
-        if self.data == "VAT_H":
-            self.vat_history(msg)
-        elif self.data == "SH_RUN":
-            self.show_run(msg)
-
-    def end_message(self, msg):
-        """Called when message ends. Default implementation does nothing.
-
-        :param msg: Message to process.
-        :type msg: Message
-        :returns: Nothing.
-        """
-        pass
-
-    def vat_history(self, msg):
-        """Called when extraction of VAT command history is required.
-
-        :param msg: Message to process.
-        :type msg: Message
-        :returns: Nothing.
-        """
-        if msg.message.count("VAT command history:"):
-            self.lookup_msg_nr += 1
-            text = re.sub("[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3} "
-                          "VAT command history:", "", msg.message, count=1).\
-                replace('\n', ' |br| ').replace('\r', '').replace('"', "'")
-            if self.lookup_msg_nr > 1:
-                sys.stdout.write(" |br| ")
-            sys.stdout.write("*DUT" + str(self.lookup_msg_nr) + ":*" + text)
-
-    def show_run(self, msg):
-        """Called when extraction of VPP operational data (output of CLI command
-        Show Runtime) is required.
-
-        :param msg: Message to process.
-        :type msg: Message
-        :returns: Nothing.
-        """
-        if msg.message.count("vat# Thread "):
-            self.lookup_msg_nr += 1
-            text = msg.message.replace("vat# ", "").\
-                replace("return STDOUT ", "").replace('\n', ' |br| ').\
-                replace('\r', '').replace('"', "'")
-            if self.lookup_msg_nr == 1:
-                sys.stdout.write("*DUT" + str(self.lookup_kw_nr) +
-                                 ":* |br| " + text)
-
-
-def do_html(data, args):
-    """Generation of a html file from json data.
-
-    :param data: List of suites from json file.
-    :param args: Parsed arguments.
-    :type data: list of dict
-    :type args: ArgumentParser
-    :returns: Nothing.
-    """
-
-    shift = int(args.level)
-    start = int(args.start)
-
-    output = open(args.output, 'w')
-
-    output.write('<html>')
-    for item in data:
-        if int(item['level']) < start:
-            continue
-        level = str(int(item['level']) - start + shift)
-        output.write('<h' + level + '>' + item['title'].lower() +
-                     '</h' + level + '>')
-        output.write('<p>' + re.sub(r"(\*)(.*?)(\*)", r"<b>\2</b>", item['doc'],
-                                    0, flags=re.MULTILINE).
-                     replace(' |br| ', '<br>') + '</p>')
-        try:
-            output.write(gen_html_table(item['tests']))
-        except KeyError:
-            continue
-    output.write('</html>')
-    output.close()
-
-
-def gen_html_table(data):
-    """Generates a table with TCs' names and VAT command histories / VPP
-    operational data in html format. There is no css used.
-
-    :param data: Json data representing a table with TCs.
-    :type data: str
-    :returns: Table with TCs' names and VAT command histories / VPP operational
-    data in html format.
-    :rtype: str
-    """
-
-    table = '<table width=100% border=1><tr>'
-    table += '<th width=30%>' + data[-1][0] + '</th>'
-    table += '<th width=70%>' + data[-1][1] + '</th></tr>'
-
-    for item in data[0:-1]:
-        table += '<tr>'
-        for element in item:
-            table += '<td>' + re.sub(r"(\*)(.*?)(\*)", r"<b>\2</b>", element,
-                                     0, flags=re.MULTILINE).\
-                replace(' |br| ', '<br>').replace(' |prein| ', '<pre>').\
-                replace(' |preout| ', '</pre>') + '</td>'
-    table += '</tr></table>'
-
-    return table
-
-
-def do_rst(data, args):
-    """Generation of a rst file from json data.
-
-    :param data: List of suites from json file.
-    :param args: Parsed arguments.
-    :type data: list of dict
-    :type args: ArgumentParser
-    :returns: Nothing.
-    """
-
-    hdrs = ['=', '-', '`', "'", '.', '~', '*', '+', '^']
-    shift = int(args.level)
-    start = int(args.start)
-
-    output = open(args.output, 'w')
-    output.write('\n.. |br| raw:: html\n\n    <br />\n\n')
-    output.write('\n.. |prein| raw:: html\n\n    <pre>\n\n')
-    output.write('\n.. |preout| raw:: html\n\n    </pre>\n\n')
-
-    if args.title:
-        output.write(args.title + '\n' +
-                     hdrs[shift - 1] *
-                     len(args.title) + '\n\n')
-
-    for item in data:
-        if int(item['level']) < start:
-            continue
-        if 'ndrchk' in item['title'].lower():
-            continue
-        output.write(item['title'].lower() + '\n' +
-                     hdrs[int(item['level']) - start + shift] *
-                     len(item['title']) + '\n\n')
-        output.write(item['doc'].replace('*', '**').replace('|br|', '\n\n -') +
-                     '\n\n')
-        try:
-            test_set = list()
-            for test in item['tests']:
-                test_data = list()
-                test_data.append(test[0])
-                test_data.append(test[1].replace('*', '**'))
-                test_set.append(test_data)
-            output.write(gen_rst_table(test_set) + '\n\n')
-        except KeyError:
-            continue
-    output.close()
-
-
-def gen_rst_table(data):
-    """Generates a table with TCs' names and VAT command histories / VPP
-    operational data in rst format.
-
-    :param data: Json data representing a table with TCs.
-    :type data: str
-    :returns: Table with TCs' names and VAT command histories / VPP operational
-    data in rst format.
-    :rtype: str
-    """
-
-    table = []
-    # max size of each column
-    lengths = map(max, zip(*[[len(str(elt)) for elt in item] for item in data]))
-
-    start_of_line = '| '
-    vert_separator = ' | '
-    end_of_line = ' |'
-    line_marker = '-'
-
-    meta_template = vert_separator.join(['{{{{{0}:{{{0}}}}}}}'.format(i)
-                                         for i in range(len(lengths))])
-    template = '{0}{1}{2}'.format(start_of_line, meta_template.format(*lengths),
-                                  end_of_line)
-    # determine top/bottom borders
-    to_separator = string.maketrans('| ', '+-')
-    start_of_line = start_of_line.translate(to_separator)
-    vert_separator = vert_separator.translate(to_separator)
-    end_of_line = end_of_line.translate(to_separator)
-    separator = '{0}{1}{2}'.format(start_of_line, vert_separator.
-                                   join([x * line_marker for x in lengths]),
-                                   end_of_line)
-    # determine header separator
-    th_separator_tr = string.maketrans('-', '=')
-    start_of_line = start_of_line.translate(th_separator_tr)
-    line_marker = line_marker.translate(th_separator_tr)
-    vertical_separator = vert_separator.translate(th_separator_tr)
-    end_of_line = end_of_line.translate(th_separator_tr)
-    th_separator = '{0}{1}{2}'.format(start_of_line, vertical_separator.
-                                      join([x * line_marker for x in lengths]),
-                                      end_of_line)
-    # prepare table
-    table.append(separator)
-    # set table header
-    titles = data[-1]
-    table.append(template.format(*titles))
-    table.append(th_separator)
-    # generate table rows
-    for item in data[0:-2]:
-        table.append(template.format(item[0], item[1]))
-        table.append(separator)
-    table.append(template.format(data[-2][0], data[-2][1]))
-    table.append(separator)
-    return '\n'.join(table)
-
-
-def do_md(data, args):
-    """Generation of a rst file from json data.
-
-    :param data: List of suites from json file.
-    :param args: Parsed arguments.
-    :type data: list of dict
-    :type args: ArgumentParser
-    :returns: Nothing.
-    """
-    raise NotImplementedError("Export to 'md' format is not implemented.")
-
-
-def do_wiki(data, args):
-    """Generation of a wiki page from json data.
-
-    :param data: List of suites from json file.
-    :param args: Parsed arguments.
-    :type data: list of dict
-    :type args: ArgumentParser
-    :returns: Nothing.
-    """
-
-    shift = int(args.level)
-    start = int(args.start)
-
-    output = open(args.output, 'w')
-
-    for item in data:
-        if int(item['level']) < start:
-            continue
-        if 'ndrchk' in item['title'].lower():
-            continue
-        mark = "=" * (int(item['level']) - start + shift) + ' '
-        output.write(mark + item['title'].lower() + mark + '\n')
-        try:
-            output.write(gen_wiki_table(item['tests'], mark) +
-                         '\n\n')
-        except KeyError:
-            continue
-    output.close()
-
-
-def gen_wiki_table(data, mark):
-    """Generates a table with TCs' names and VAT command histories / VPP
-    operational data in wiki format.
-
-    :param data: Json data representing a table with TCs.
-    :type data: str
-    :returns: Table with TCs' names and VAT command histories / VPP operational
-    data in wiki format.
-    :rtype: str
-    """
-
-    table = '{| class="wikitable"\n'
-    header = ""
-    mark = mark[0:-2] + "= "
-    for item in data[-1]:
-        header += '!{}\n'.format(item)
-    table += header
-    for item in data[0:-1]:
-        msg = item[1].replace('*', mark).replace(' |br| ', '\n\n').\
-            replace(' |prein| ', '<pre>').replace(' |preout| ', '</pre>')
-        table += '|-\n|{}\n|{}\n'.format(item[0], msg)
-    table += '|}\n'
-
-    return table
-
-
-def process_robot_file(args):
-    """Process data from robot output.xml file and generate defined file type.
-
-    :param args: Parsed arguments.
-    :type args: ArgumentParser
-    :return: Nothing.
-    """
-
-    old_sys_stdout = sys.stdout
-    sys.stdout = open(args.output + '.json', 'w')
-
-    result = ExecutionResult(args.input)
-    checker = ExecutionChecker(args)
-
-    sys.stdout.write('[')
-    result.visit(checker)
-    sys.stdout.write('{}]')
-    sys.stdout.close()
-    sys.stdout = old_sys_stdout
-
-    with open(args.output + '.json', 'r') as json_file:
-        data = json.load(json_file)
-    data.pop(-1)
-
-    if args.regex:
-        results = list()
-        regex = re.compile(args.regex)
-        for item in data:
-            if re.search(regex, item['title'].lower()):
-                results.append(item)
-    else:
-        results = data
-
-    if args.formatting == 'rst':
-        do_rst(results, args)
-    elif args.formatting == 'wiki':
-        do_wiki(results, args)
-    elif args.formatting == 'html':
-        do_html(results, args)
-    elif args.formatting == 'md':
-        do_md(results, args)
-
-
-def parse_args():
-    """Parse arguments from cmd line.
-
-    :return: Parsed arguments.
-    :rtype ArgumentParser
-    """
-
-    parser = argparse.ArgumentParser(description=__doc__,
-                                     formatter_class=argparse.
-                                     RawDescriptionHelpFormatter)
-    parser.add_argument("-i", "--input",
-                        required=True,
-                        type=argparse.FileType('r'),
-                        help="Robot XML log file")
-    parser.add_argument("-o", "--output",
-                        type=str,
-                        required=True,
-                        help="Output file")
-    parser.add_argument("-d", "--data",
-                        type=str,
-                        required=True,
-                        help="Required data: VAT_H (VAT history), SH_RUN "
-                             "(show runtime output)")
-    parser.add_argument("-f", "--formatting",
-                        required=True,
-                        choices=['html', 'wiki', 'rst', 'md'],
-                        help="Output file format")
-    parser.add_argument("-s", "--start",
-                        type=int,
-                        default=1,
-                        help="The first level to be taken from xml file")
-    parser.add_argument("-l", "--level",
-                        type=int,
-                        default=1,
-                        help="The level of the first chapter in generated file")
-    parser.add_argument("-r", "--regex",
-                        type=str,
-                        default=None,
-                        help="Regular expression used to select test suites. "
-                             "If None, all test suites are selected.")
-    parser.add_argument("-t", "--title",
-                        type=str,
-                        default=None,
-                        help="Title of the output.")
-
-    return parser.parse_args()
-
-
-if __name__ == "__main__":
-    sys.exit(process_robot_file(parse_args()))