aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/02_vswitch.conf3
-rw-r--r--conf/12_k8s.conf10
-rw-r--r--conf/kubernetes/01_testcases.conf20
-rw-r--r--core/pod_controller.py13
-rw-r--r--pods/papi/papi.py21
-rwxr-xr-xsrc/dpdk/Makefile2
-rw-r--r--src/package-list.mk6
-rw-r--r--systems/README.md12
-rwxr-xr-xsystems/centos/build_base_machine.sh1
-rwxr-xr-xsystems/centos/prepare_python_env.sh1
-rw-r--r--systems/fedora/33/build_base_machine.sh75
-rw-r--r--systems/fedora/33/prepare_python_env.sh30
-rwxr-xr-xsystems/ubuntu/20.04/build_base_machine.sh94
-rwxr-xr-xsystems/ubuntu/20.04/prepare_python_env.sh29
-rw-r--r--testcases/testcase.py12
-rw-r--r--tools/extvswitchflctl.py129
-rw-r--r--tools/k8s/reference-definitions/network-attachments/ovsdpdk/userspace-ovs-netAttach.yaml32
-rwxr-xr-xtools/k8s/reference-definitions/network-attachments/sriov/attach-order.sh4
-rw-r--r--tools/k8s/reference-definitions/network-attachments/sriov/configMap.yaml30
-rw-r--r--tools/k8s/reference-definitions/network-attachments/sriov/netAttach-sriov-dpdk-b.yaml14
-rw-r--r--tools/k8s/reference-definitions/network-attachments/sriov/netAttach-sriov-dpdk.yaml14
-rw-r--r--tools/k8s/reference-definitions/network-attachments/sriov/sriovdp-daemonset.yaml66
-rw-r--r--tools/k8s/reference-definitions/network-attachments/vpp/userspace-vpp-netAttach-memif.yaml32
-rw-r--r--tools/k8s/reference-definitions/pod-defs/ovsdpdk/userspace-ovs-netapp-pod.yaml47
-rw-r--r--tools/k8s/reference-definitions/pod-defs/sriov/sriov-pod.yaml47
-rw-r--r--tools/k8s/reference-definitions/pod-defs/vpp/userspace-dpdk-pod.yaml49
-rw-r--r--tools/k8s/reference-definitions/pod-defs/vpp/userspace-dpdk-pod2.yaml47
-rw-r--r--tools/k8s/test-containers/dpdk-forwarding-pods/Dockerfile110
-rw-r--r--tools/k8s/test-containers/trafficgen-pods/pktgen/Dockerfile48
-rw-r--r--tools/pkt_fwd/dummy.py62
30 files changed, 1042 insertions, 18 deletions
diff --git a/conf/02_vswitch.conf b/conf/02_vswitch.conf
index 4eca1a52..7a29fc70 100644
--- a/conf/02_vswitch.conf
+++ b/conf/02_vswitch.conf
@@ -250,3 +250,6 @@ VSWITCH_VPP_L2_CONNECT_MODE = 'xconnect'
# Options used during creation of dpdkvhostuser interface
VSWITCH_VPP_VHOSTUSER_ARGS = ['feature-mask', '0xFF']
+
+EXT_VSWITCH_VPP_FLOWCTL = 'vppctl'
+EXT_VSWITCH_OVS_FLOWCTL = 'ovs-ofctl'
diff --git a/conf/12_k8s.conf b/conf/12_k8s.conf
index 5cfac966..545870cd 100644
--- a/conf/12_k8s.conf
+++ b/conf/12_k8s.conf
@@ -32,10 +32,16 @@ WORKER_PASSWD = 'opnfv'
PLUGIN = 'ovsdpdk'
# Paths. Default location: Master Node.
-NETWORK_ATTACHMENT_FILEPATH = ['/home/opnfv/sridhar/cnb/userspace/ovsdpdk/userspace-ovs-netAttach.yaml']
-POD_MANIFEST_FILEPATH = '/home/opnfv/sridhar/cnb/userspace/ovsdpdk/userspace-ovs-netapp-pod.yaml'
+# NETWORK_ATTACHMENT_FILEPATH = ['/home/opnfv/sridhar/cnb/userspace/ovsdpdk/userspace-ovs-netAttach.yaml']
+NETWORK_ATTACHMENT_FILEPATH = ['/home/opnfv/sridhar/cnb/userspace/vpp/userspace-vpp-netAttach-memif.yaml']
+#POD_MANIFEST_FILEPATH = '/home/opnfv/sridhar/cnb/userspace/ovsdpdk/userspace-ovs-netapp-pod.yaml'
+POD_MANIFEST_FILEPATH = ['/home/opnfv/sridhar/cnb/userspace/vpp/userspace-dpdk-pod.yaml',
+ '/home/opnfv/sridhar/cnb/userspace/vpp/userspace-dpdk-pod2.yaml']
# Application pod
APP_NAME = 'l2fwd'
+EXT_VSWITCH = True
+EXT_VSWITCH_TYPE = 'VPP'
+EXT_OVS_BRIDGE = 'br0'
diff --git a/conf/kubernetes/01_testcases.conf b/conf/kubernetes/01_testcases.conf
index c5b3135c..25eea362 100644
--- a/conf/kubernetes/01_testcases.conf
+++ b/conf/kubernetes/01_testcases.conf
@@ -9,4 +9,24 @@ K8SPERFORMANCE_TESTS = [
},
},
},
+ {
+ "Name": "pcp_evs_tput",
+ "Deployment": "pcp",
+ "Description": "LTD.Throughput.RFC2544.Throughput",
+ "Parameters" : {
+ "TRAFFIC" : {
+ "traffic_type" : "rfc2544_throughput",
+ },
+ },
+ },
+ {
+ "Name": "pccp_evs_tput",
+ "Deployment": "pccp",
+ "Description": "LTD.Throughput.RFC2544.Throughput",
+ "Parameters" : {
+ "TRAFFIC" : {
+ "traffic_type" : "rfc2544_throughput",
+ },
+ },
+ },
]
diff --git a/core/pod_controller.py b/core/pod_controller.py
index 8bc91ec4..109daa43 100644
--- a/core/pod_controller.py
+++ b/core/pod_controller.py
@@ -16,7 +16,7 @@
import logging
import pexpect
-#from conf import settings
+from conf import settings
from pods.pod.pod import IPod
class PodController():
@@ -44,12 +44,15 @@ class PodController():
self._pod_class = pod_class
self._deployment = deployment.lower()
self._pods = []
- if self._deployment == 'p2p':
+ if 'pcp' in self._deployment or 'p2p' in self._deployment:
pod_number = 1
-
+ elif 'pccp'in self._deployment:
+ pod_number = 2
+ print("POD COUNTING DONE")
+ settings.setValue('POD_COUNT', pod_number)
+ # we will have single controller for all pods
if pod_number:
- self._pods = [pod_class() for _ in range(pod_number)]
-
+ self._pods.append(pod_class())
self._logger.debug('Initializing the pod')
def get_pods(self):
diff --git a/pods/papi/papi.py b/pods/papi/papi.py
index 5a21f1d6..5a96660d 100644
--- a/pods/papi/papi.py
+++ b/pods/papi/papi.py
@@ -49,9 +49,12 @@ class Papi(IPod):
"""
Creation Process
"""
+ print("Entering Create Function")
# create vswitchperf namespace
api = client.CoreV1Api()
namespace = 'default'
+ pod_manifests = S.getValue('POD_MANIFEST_FILEPATH')
+ pod_count = int(S.getValue('POD_COUNT'))
#namespace = 'vswitchperf'
# replace_namespace(api, namespace)
@@ -68,6 +71,8 @@ class Papi(IPod):
version = 'v1'
kind_plural = 'network-attachment-definitions'
api = client.CustomObjectsApi()
+
+ assert pod_count <= len(pod_manifests)
for nad_filepath in S.getValue('NETWORK_ATTACHMENT_FILEPATH'):
nad_manifest = load_manifest(nad_filepath)
@@ -81,15 +86,17 @@ class Papi(IPod):
raise Exception from err
#create pod workloads
- pod_manifest = load_manifest(S.getValue('POD_MANIFEST_FILEPATH'))
api = client.CoreV1Api()
+
+ for count in range(pod_count):
+ pod_manifest = load_manifest(pod_manifests[count])
- try:
- response = api.create_namespaced_pod(namespace, pod_manifest)
- self._logger.info(str(response))
- self._logger.info("Created POD %d ...", self._number)
- except ApiException as err:
- raise Exception from err
+ try:
+ response = api.create_namespaced_pod(namespace, pod_manifest)
+ self._logger.info(str(response))
+ self._logger.info("Created POD %d ...", self._number)
+ except ApiException as err:
+ raise Exception from err
time.sleep(12)
diff --git a/src/dpdk/Makefile b/src/dpdk/Makefile
index 1a1521db..0a4b9724 100755
--- a/src/dpdk/Makefile
+++ b/src/dpdk/Makefile
@@ -54,7 +54,7 @@ ifeq ($(DPDK_TAG_MAJOR),v2)
else
DPDK_TARGET = x86_64-native-linuxapp-gcc
CONFIG_FILE_BASE = $(WORK_DIR)/config/common_base
- CONFIG_FILE_LINUXAPP = $(WORK_DIR)/config/common_linuxapp
+ CONFIG_FILE_LINUXAPP = $(WORK_DIR)/config/common_linux
endif
endif
diff --git a/src/package-list.mk b/src/package-list.mk
index 1e40a60d..49aa82c0 100644
--- a/src/package-list.mk
+++ b/src/package-list.mk
@@ -13,15 +13,15 @@
# dpdk section
# DPDK_URL ?= git://dpdk.org/dpdk
DPDK_URL ?= http://dpdk.org/git/dpdk
-DPDK_TAG ?= v18.11-rc2
+DPDK_TAG ?= v20.05
# OVS section
OVS_URL ?= https://github.com/openvswitch/ovs
-OVS_TAG ?= v2.12.0
+OVS_TAG ?= v2.14.0
# VPP section
VPP_URL ?= https://git.fd.io/vpp
-VPP_TAG ?= v19.08.1
+VPP_TAG ?= v21.01
# QEMU section
QEMU_URL ?= https://github.com/qemu/qemu.git
diff --git a/systems/README.md b/systems/README.md
index ca6557ea..60f903c1 100644
--- a/systems/README.md
+++ b/systems/README.md
@@ -16,3 +16,15 @@ or with password less sudo access.
If you want to use vsperf in trafficgen-mode ONLY, then add a parameter.
./build_base_machine.sh trafficgen
+
+
+Newer Kernel Versions:
+----------------------
+
+May need following changes:
+
+1. In src/l2fwd/l2fwd.c, comment out the line with xmit_more (193).
+
+2. In src/qemu/Makefile, In line 30, we MAY have to add the following:
+ --disable-werror --python='/usr/bin/python3'
+
diff --git a/systems/centos/build_base_machine.sh b/systems/centos/build_base_machine.sh
index 0e1ed830..fdaa37b5 100755
--- a/systems/centos/build_base_machine.sh
+++ b/systems/centos/build_base_machine.sh
@@ -78,6 +78,7 @@ sudo yum -y install centos-release-scl-rh
yum -y install $(echo "
rh-python36
rh-python36-python-tkinter
+python3-setuptools
git-review
" | grep -v ^#)
# prevent ovs vanilla from building from source due to kernel incompatibilities
diff --git a/systems/centos/prepare_python_env.sh b/systems/centos/prepare_python_env.sh
index 4f5c0065..bbc853b2 100755
--- a/systems/centos/prepare_python_env.sh
+++ b/systems/centos/prepare_python_env.sh
@@ -24,5 +24,6 @@ fi
scl enable rh-python36 "
virtualenv "$VSPERFENV_DIR" --python /opt/rh/rh-python36/root/usr/bin/python3
source "$VSPERFENV_DIR"/bin/activate
+pip install -U pip
pip install -r ../requirements.txt
"
diff --git a/systems/fedora/33/build_base_machine.sh b/systems/fedora/33/build_base_machine.sh
new file mode 100644
index 00000000..f521827e
--- /dev/null
+++ b/systems/fedora/33/build_base_machine.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+#
+# Build a base machine for Fedora 26
+#
+# Copyright 2017 OPNFV, Intel Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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.
+
+dnf -y install $(echo "
+# Make and Compilers
+make
+automake
+gcc
+gcc-c++
+libxml2
+glibc
+glib2-devel
+kernel-devel
+fuse-libs
+fuse
+fuse-devel
+kernel-modules-extra
+pixman-devel
+openssl-devel
+redhat-rpm-config
+elfutils-libelf-devel
+
+# tools
+curl
+autoconf
+libtool
+libpcap-devel
+libnet
+vim
+wget
+git
+pciutils
+cifs-utils
+socat
+sysstat
+sshpass
+
+# install python packages
+python3-virtualenv
+python3-setuptools
+python3-pip
+python3-dbus
+python3-devel
+python3-tkinter
+systemd-python3
+python3-libs
+python3-libreport
+python3-abrt
+python3-abrt-addon
+
+# libs
+numactl
+numactl-devel
+
+# install git-review tool
+git-review
+" | grep -v ^#)
+
+# Create hugepage dirs
+mkdir -p /dev/hugepages
diff --git a/systems/fedora/33/prepare_python_env.sh b/systems/fedora/33/prepare_python_env.sh
new file mode 100644
index 00000000..becfd5ca
--- /dev/null
+++ b/systems/fedora/33/prepare_python_env.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Prepare Python environment for vsperf execution on Fedora 26 systems.
+#
+# Copyright 2017 OPNFV, Intel Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if [ -d "$VSPERFENV_DIR" ] ; then
+ echo "Directory $VSPERFENV_DIR already exists. Skipping python virtualenv creation."
+ exit
+fi
+
+# enable virtual environment in a subshell, so QEMU build can use python 2.7
+
+(virtualenv "$VSPERFENV_DIR" --python /usr/bin/python3
+source "$VSPERFENV_DIR"/bin/activate
+pip install -U pip
+pip install -r ../requirements.txt
+pip install six)
diff --git a/systems/ubuntu/20.04/build_base_machine.sh b/systems/ubuntu/20.04/build_base_machine.sh
new file mode 100755
index 00000000..ab30c347
--- /dev/null
+++ b/systems/ubuntu/20.04/build_base_machine.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+#
+# Build a base machine for Ubuntu 14.04
+#
+# Copyright 2015 OPNFV, Intel Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Contributors:
+# Aihua Li, Huawei Technologies.
+# Martin Klozik, Intel Corporation.
+# Abdul Halim, Intel Corporation.
+
+apt-get update
+apt-get -y install $(echo "
+# Make and Compilers
+make
+automake
+gcc
+g++
+libc6
+libc6-dev
+libxml2
+fuse
+libfuse2
+libfuse-dev
+libssl-dev
+libglib2.0-dev
+zlib1g-dev
+
+# Linux Kernel Source
+linux-source
+linux-headers-$(uname -r)
+pkg-config
+
+# tools
+curl
+libcurl4-openssl-dev
+automake
+autoconf
+libtool
+libpcap-dev
+libnet1
+libncurses5-dev
+vim
+wget
+git
+pciutils
+cifs-utils
+socat
+libpixman-1-0
+libpixman-1-dev
+sysstat
+sshpass
+
+# Java runtime environment: Required for Ixia TclClient
+default-jre
+
+# install python packages
+python3-pip
+python3-setuptools
+python3-dbus
+python3-dev
+python3-tk
+python3-venv
+libpython3.8
+python3-reportlab
+
+# libs
+libnuma1
+libnuma-dev
+
+# install git-review tool
+git-review
+" | grep -v ^#)
+
+# fix: Ixia TclClient installation: cannot find 'libc.s0.6'
+ln -sf $(locate libc.so.6) /lib/libc.so.6
+
+# Install virtualenv
+pip3 install virtualenv
+
+# Create hugepage dirs
+mkdir -p /dev/hugepages
diff --git a/systems/ubuntu/20.04/prepare_python_env.sh b/systems/ubuntu/20.04/prepare_python_env.sh
new file mode 100755
index 00000000..c44a3bdd
--- /dev/null
+++ b/systems/ubuntu/20.04/prepare_python_env.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+#
+# Prepare Python environment for vsperf execution on Ubuntu 14.04 systems
+#
+# Copyright 2015-2017 OPNFV, Intel Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if [ -d "$VSPERFENV_DIR" ] ; then
+ echo "Directory $VSPERFENV_DIR already exists. Skipping python virtualenv creation."
+ exit
+fi
+
+# enable virtual environment in a subshell, so QEMU build can use python 2.7
+
+(virtualenv "$VSPERFENV_DIR" --python /usr/bin/python3
+source "$VSPERFENV_DIR"/bin/activate
+pip install -U pip
+pip install -r ../requirements.txt)
diff --git a/testcases/testcase.py b/testcases/testcase.py
index c300bfc1..40bec186 100644
--- a/testcases/testcase.py
+++ b/testcases/testcase.py
@@ -35,6 +35,7 @@ from tools import hugepages
from tools import functions
from tools import namespace
from tools import veth
+from tools import extvswitchflctl
from tools.teststepstools import TestStepsTools
from tools.llc_management import rmd
@@ -76,6 +77,7 @@ class TestCase(object):
self._pod_ctl = None
self._pod_list = None
self._vswitch_ctl = None
+ self._evfctl = None
self._collector = None
self._loadgen = None
self._output_file = None
@@ -203,6 +205,10 @@ class TestCase(object):
# If running in k8s mode.
# This value is set in main vsperf file
self._k8s = S.getValue('K8S')
+ if self._k8s:
+ if S.getValue('EXT_VSWITCH'):
+ self._evfctl = extvswitchfctl.ExtVswitchFlowCtl()
+
def run_initialize(self):
""" Prepare test execution environment
@@ -619,6 +625,12 @@ class TestCase(object):
Add connections for Kubernetes Usecases
"""
logging.info("Kubernetes: Adding Connections")
+ if self._evfctl:
+ self._evfctl.add_connections()
+ return
+ if self._vswitch_none:
+ logging.info("Vswitch cannot be None when switch is not external")
+ return
vswitch = self._vswitch_ctl.get_vswitch()
bridge = S.getValue('VSWITCH_BRIDGE_NAME')
if S.getValue('K8S') and 'sriov' not in S.getValue('PLUGIN'):
diff --git a/tools/extvswitchflctl.py b/tools/extvswitchflctl.py
new file mode 100644
index 00000000..56eeafd0
--- /dev/null
+++ b/tools/extvswitchflctl.py
@@ -0,0 +1,129 @@
+"""
+Tool to configure flows for Kubernetes Usecases.
+"""
+
+from tools import tasks
+from conf import settings as S
+
+class ExtVswitchFlowCtl(tasks.Process):
+ """
+ Virtual Switch Flow Control
+ """
+ def __init__(self):
+ """
+ Initialization
+ """
+ super().__init__()
+ self._vpp_ctl = ['sudo', S.getValue('EXT_VSWITCH_VPP_FLOWCTL')]
+ self._ovs_ctl = ['sudo', S.getValue('EXT_VSWITCH_OVS_FLOWCTL')]
+
+ def get_vpp_interfaces(self):
+ """
+ Get VPP interfaces Names
+ """
+ ifargs = ['show', 'interface']
+ output = self.run_vppctl(ifargs)
+ ifaces = output[0].split('\n')
+ pifaces = []
+ vifaces = []
+ for iface in ifaces:
+ name = iface.split()[0]
+ if 'Name' in name or 'local' in name:
+ continue
+ if 'Ethernet' in name:
+ pifaces.append(name)
+ if 'memif' in name:
+ vifaces.append(name)
+ assert len(vifaces) == 2 or len(vifaces) == 4
+ assert len(pifaces) == 2
+ assert pifaces[0][:-1] in pifaces[1][:-1]
+ return pifaces, vifaces
+
+ def add_connections(self):
+ """
+ Add Connections of OVS or VPP
+ """
+ if 'VPP' in S.getValue('EXT_VSWITCH_TYPE'):
+ self.add_vpp_xconnect()
+ else:
+ self.add_ovs_xconnect()
+
+ def add_ovs_xconnect(self):
+ """
+ Add connections to OVS
+ """
+ entries = [['--timeout', '10', '-o', 'OpenFlow13', 'add-flow',
+ S.getValue('EXT_VSWITCH_OVS_BRIDGE'),
+ 'in_port=1,idle_timeout=0,action=output:3'],
+ ['--timeout', '10', '-o', 'OpenFlow13', 'add-flow',
+ S.getValue('EXT_VSWITCH_OVS_BRIDGE'),
+ 'in_port=3,idle_timeout=0,action=output:1'],
+ ['--timeout', '10', '-o', 'OpenFlow13', 'add-flow',
+ S.getValue('EXT_VSWITCH_OVS_BRIDGE'),
+ 'in_port=2,idle_timeout=0,action=output:4'],
+ ['--timeout', '10', '-o', 'OpenFlow13', 'add-flow',
+ S.getValue('EXT_VSWITCH_OVS_BRIDGE'),
+ 'in_port=4,idle_timeout=0,action=output:2']]
+ for entry in entries:
+ self.run_ovsfctl(entry)
+
+ def add_vpp_xconnect(self):
+ """
+ Add Connections to VPP
+ """
+ pifaces, vifaces = self.get_vpp_interfaces()
+ # Bring Physical interface up - In case it is down.
+ for piface in pifaces:
+ ifargs = ['set', 'interface', 'state', piface, 'up']
+ self.run_vppctl(ifargs)
+ if len(vifaces) == 2:
+ entries = [['test', 'l2patch', 'rx',
+ pifaces[0], 'tx', vifaces[0]],
+ ['test', 'l2patch', 'rx',
+ vifaces[0], 'tx', pifaces[0]],
+ ['test', 'l2patch', 'rx',
+ pifaces[1], 'tx', vifaces[1]],
+ ['test', 'l2patch', 'rx',
+ vifaces[1], 'tx', pifaces[1]]]
+ elif len(vifaces) == 4:
+ entries = [['test', 'l2patch', 'rx',
+ pifaces[0], 'tx', vifaces[0]],
+ ['test', 'l2patch', 'rx',
+ vifaces[0], 'tx', pifaces[0]],
+ ['test', 'l2patch', 'rx',
+ vifaces[1], 'tx', vifaces[2]],
+ ['test', 'l2patch', 'rx',
+ vifaces[2], 'tx', vifaces[1]],
+ ['test', 'l2patch', 'rx',
+ pifaces[1], 'tx', vifaces[3]],
+ ['test', 'l2patch', 'rx',
+ vifaces[3], 'tx', pifaces[1]]]
+
+ for entry in entries:
+ self.run_vppctl(entry)
+
+ def run_ovsfctl(self, args, check_error=False):
+ """Run ``ovs-ofctl`` with supplied arguments.
+
+ :param args: Arguments to pass to ``vppctl``
+ :param check_error: Throw exception on error
+
+ :return: None
+ """
+ cmd = self._ovs_ctl + args
+ return tasks.run_task(cmd, self._logger,
+ 'Running ovs-ofctl...',
+ check_error)
+
+ def run_vppctl(self, args, check_error=False):
+ """Run ``vppctl`` with supplied arguments.
+
+ :param args: Arguments to pass to ``vppctl``
+ :param check_error: Throw exception on error
+
+ :return: None
+ """
+ cmd = self._vpp_ctl + args
+ return tasks.run_task(cmd, self._logger,
+ 'Running vppctl...',
+ check_error)
diff --git a/tools/k8s/reference-definitions/network-attachments/ovsdpdk/userspace-ovs-netAttach.yaml b/tools/k8s/reference-definitions/network-attachments/ovsdpdk/userspace-ovs-netAttach.yaml
new file mode 100644
index 00000000..b2ac5c7c
--- /dev/null
+++ b/tools/k8s/reference-definitions/network-attachments/ovsdpdk/userspace-ovs-netAttach.yaml
@@ -0,0 +1,32 @@
+apiVersion: "k8s.cni.cncf.io/v1"
+kind: NetworkAttachmentDefinition
+metadata:
+ name: userspace-ovs-net
+spec:
+ config: '{
+ "cniVersion": "0.3.1",
+ "type": "userspace",
+ "name": "userspace-ovs-net-1",
+ "kubeconfig": "/etc/cni/net.d/multus.d/multus.kubeconfig",
+ "logFile": "/var/log/userspace-ovs-net.log",
+ "logLevel": "debug",
+ "host": {
+ "engine": "ovs-dpdk",
+ "iftype": "vhostuser",
+ "netType": "bridge",
+ "vhost": {
+ "mode": "server"
+ },
+ "bridge": {
+ "bridgeName": "vsperf-br0"
+ }
+ },
+ "container": {
+ "engine": "ovs-dpdk",
+ "iftype": "vhostuser",
+ "netType": "interface",
+ "vhost": {
+ "mode": "client"
+ }
+ }
+ }'
diff --git a/tools/k8s/reference-definitions/network-attachments/sriov/attach-order.sh b/tools/k8s/reference-definitions/network-attachments/sriov/attach-order.sh
new file mode 100755
index 00000000..9ffac806
--- /dev/null
+++ b/tools/k8s/reference-definitions/network-attachments/sriov/attach-order.sh
@@ -0,0 +1,4 @@
+kubectl create -f netAttach-sriov-dpdk-a.yaml
+kubectl create -f netAttach-sriov-dpdk-b.yaml
+kubectl create -f configMap.yaml
+kubectl create -f sriovdp-daemonset.yaml
diff --git a/tools/k8s/reference-definitions/network-attachments/sriov/configMap.yaml b/tools/k8s/reference-definitions/network-attachments/sriov/configMap.yaml
new file mode 100644
index 00000000..53461c0f
--- /dev/null
+++ b/tools/k8s/reference-definitions/network-attachments/sriov/configMap.yaml
@@ -0,0 +1,30 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: sriovdp-config
+ namespace: kube-system
+data:
+ config.json: |
+ {
+ "resourceList": [{
+ "resourceName": "intel_sriov_dpdk_a",
+ "selectors": {
+ "vendors": ["8086"],
+ "devices": ["10ed"],
+ "drivers": ["vfio-pci"],
+ "pfNames": ["eno3"]
+ }
+ },
+ {
+ "resourceName": "intel_sriov_dpdk_b",
+ "selectors": {
+ "vendors": ["8086"],
+ "devices": ["10ed"],
+ "drivers": ["vfio-pci"],
+ "pfNames": ["eno4"]
+ }
+ }
+
+ ]
+ }
+
diff --git a/tools/k8s/reference-definitions/network-attachments/sriov/netAttach-sriov-dpdk-b.yaml b/tools/k8s/reference-definitions/network-attachments/sriov/netAttach-sriov-dpdk-b.yaml
new file mode 100644
index 00000000..c876d76d
--- /dev/null
+++ b/tools/k8s/reference-definitions/network-attachments/sriov/netAttach-sriov-dpdk-b.yaml
@@ -0,0 +1,14 @@
+apiVersion: "k8s.cni.cncf.io/v1"
+kind: NetworkAttachmentDefinition
+metadata:
+ name: sriov-net-b
+ annotations:
+ k8s.v1.cni.cncf.io/resourceName: intel.com/intel_sriov_dpdk_b
+spec:
+ config: '{
+ "type": "sriov",
+ "cniVersion": "0.3.1",
+ "name": "sriov-network-b",
+ "spoofchk": "off",
+ "trust": "on"
+}'
diff --git a/tools/k8s/reference-definitions/network-attachments/sriov/netAttach-sriov-dpdk.yaml b/tools/k8s/reference-definitions/network-attachments/sriov/netAttach-sriov-dpdk.yaml
new file mode 100644
index 00000000..9678ae4a
--- /dev/null
+++ b/tools/k8s/reference-definitions/network-attachments/sriov/netAttach-sriov-dpdk.yaml
@@ -0,0 +1,14 @@
+apiVersion: "k8s.cni.cncf.io/v1"
+kind: NetworkAttachmentDefinition
+metadata:
+ name: sriov-net-a
+ annotations:
+ k8s.v1.cni.cncf.io/resourceName: intel.com/intel_sriov_dpdk_a
+spec:
+ config: '{
+ "type": "sriov",
+ "cniVersion": "0.3.1",
+ "name": "sriov-network-a",
+ "spoofchk": "off",
+ "trust": "on"
+}'
diff --git a/tools/k8s/reference-definitions/network-attachments/sriov/sriovdp-daemonset.yaml b/tools/k8s/reference-definitions/network-attachments/sriov/sriovdp-daemonset.yaml
new file mode 100644
index 00000000..91a68f5b
--- /dev/null
+++ b/tools/k8s/reference-definitions/network-attachments/sriov/sriovdp-daemonset.yaml
@@ -0,0 +1,66 @@
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: sriov-device-plugin
+ namespace: kube-system
+
+---
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ name: kube-sriov-device-plugin-amd64
+ namespace: kube-system
+ labels:
+ tier: node
+ app: sriovdp
+spec:
+ selector:
+ matchLabels:
+ name: sriov-device-plugin
+ template:
+ metadata:
+ labels:
+ tier: node
+ app: sriovdp
+ name: sriov-device-plugin
+ spec:
+ hostNetwork: true
+ hostPID: true
+ nodeSelector:
+ beta.kubernetes.io/arch: amd64
+ tolerations:
+ - key: node-role.kubernetes.io/master
+ operator: Exists
+ effect: NoSchedule
+ serviceAccountName: sriov-device-plugin
+ containers:
+ - name: kube-sriovdp
+ image: nfvpe/sriov-device-plugin
+ imagePullPolicy: Never
+ args:
+ - --log-dir=sriovdp
+ - --log-level=10
+ securityContext:
+ privileged: true
+ volumeMounts:
+ - name: devicesock
+ mountPath: /var/lib/kubelet/
+ readOnly: false
+ - name: log
+ mountPath: /var/log
+ - name: config-volume
+ mountPath: /etc/pcidp
+ volumes:
+ - name: devicesock
+ hostPath:
+ path: /var/lib/kubelet/
+ - name: log
+ hostPath:
+ path: /var/log
+ - name: config-volume
+ configMap:
+ name: sriovdp-config
+ items:
+ - key: config.json
+ path: config.json
diff --git a/tools/k8s/reference-definitions/network-attachments/vpp/userspace-vpp-netAttach-memif.yaml b/tools/k8s/reference-definitions/network-attachments/vpp/userspace-vpp-netAttach-memif.yaml
new file mode 100644
index 00000000..1ac6c245
--- /dev/null
+++ b/tools/k8s/reference-definitions/network-attachments/vpp/userspace-vpp-netAttach-memif.yaml
@@ -0,0 +1,32 @@
+apiVersion: "k8s.cni.cncf.io/v1"
+kind: NetworkAttachmentDefinition
+metadata:
+ name: userspace-vpp-net
+spec:
+ config: '{
+ "cniVersion": "0.3.1",
+ "type": "userspace",
+ "name": "userspace-vpp-net",
+ "kubeconfig": "/etc/cni/net.d/multus.d/multus.kubeconfig",
+ "logFile": "/var/log/userspace-vpp-net-1-cni.log",
+ "logLevel": "debug",
+ "host": {
+ "engine": "vpp",
+ "iftype": "memif",
+ "netType": "interface",
+ "memif": {
+ "role": "master",
+ "mode": "ethernet"
+ }
+ },
+ "container": {
+ "engine": "vpp",
+ "iftype": "memif",
+ "netType": "interface",
+ "memif": {
+ "role": "slave",
+ "mode": "ethernet"
+ }
+ }
+ }'
+
diff --git a/tools/k8s/reference-definitions/pod-defs/ovsdpdk/userspace-ovs-netapp-pod.yaml b/tools/k8s/reference-definitions/pod-defs/ovsdpdk/userspace-ovs-netapp-pod.yaml
new file mode 100644
index 00000000..64f4a5cb
--- /dev/null
+++ b/tools/k8s/reference-definitions/pod-defs/ovsdpdk/userspace-ovs-netapp-pod.yaml
@@ -0,0 +1,47 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: userspace-ovs-pod
+ annotations:
+ k8s.v1.cni.cncf.io/networks: userspace-ovs-net, userspace-ovs-net
+spec:
+ containers:
+ - name: multi-vhost
+ image: dpdk-app-centos:latest
+ imagePullPolicy: Never
+ securityContext:
+ privileged: true
+ volumeMounts:
+ - mountPath: /etc/podnetinfo
+ name: podinfo
+ readOnly: false
+ - mountPath: /var/run/openvswitch/
+ name: shared-dir
+ - mountPath: /dev/hugepages
+ name: hugepage
+ resources:
+ requests:
+ cpu: "4000m"
+ hugepages-1Gi: 4Gi
+ limits:
+ cpu: "4000m"
+ hugepages-1Gi: 4Gi
+ command: ["sleep", "infinity"]
+ nodeSelector:
+ vswitch: ovs
+ volumes:
+ - name: podinfo
+ downwardAPI:
+ items:
+ - path: "labels"
+ fieldRef:
+ fieldPath: metadata.labels
+ - path: "annotations"
+ fieldRef:
+ fieldPath: metadata.annotations
+ - name: shared-dir
+ hostPath:
+ path: /usr/local/var/run/openvswitch/
+ - name: hugepage
+ emptyDir:
+ medium: HugePages
diff --git a/tools/k8s/reference-definitions/pod-defs/sriov/sriov-pod.yaml b/tools/k8s/reference-definitions/pod-defs/sriov/sriov-pod.yaml
new file mode 100644
index 00000000..2b5aff7a
--- /dev/null
+++ b/tools/k8s/reference-definitions/pod-defs/sriov/sriov-pod.yaml
@@ -0,0 +1,47 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: sriov-pod
+ annotations:
+ k8s.v1.cni.cncf.io/networks: sriov-net-a, sriov-net-b
+spec:
+ containers:
+ - name: sriov
+ image: dpdk-app-centos-numa1
+ imagePullPolicy: Never
+ securityContext:
+ privileged: true
+ capabilities:
+ add: ["CAP_SYS_ADMIN"]
+ volumeMounts:
+ - mountPath: /etc/podnetinfo
+ name: podnetinfo
+ readOnly: false
+ - mountPath: /dev/hugepages
+ name: hugepage
+ resources:
+ requests:
+ cpu: "6000m"
+ intel.com/intel_sriov_dpdk_a: '1'
+ intel.com/intel_sriov_dpdk_b: '1'
+ limits:
+ cpu: "6000m"
+ hugepages-1Gi: 2Gi
+ intel.com/intel_sriov_dpdk_a: '1'
+ intel.com/intel_sriov_dpdk_b: '1'
+ command: ["sleep", "infinity"]
+# nodeSelector:
+# vswitch: ovs
+ volumes:
+ - name: podnetinfo
+ downwardAPI:
+ items:
+ - path: "labels"
+ fieldRef:
+ fieldPath: metadata.labels
+ - path: "annotations"
+ fieldRef:
+ fieldPath: metadata.annotations
+ - name: hugepage
+ emptyDir:
+ medium: HugePages
diff --git a/tools/k8s/reference-definitions/pod-defs/vpp/userspace-dpdk-pod.yaml b/tools/k8s/reference-definitions/pod-defs/vpp/userspace-dpdk-pod.yaml
new file mode 100644
index 00000000..4b72df22
--- /dev/null
+++ b/tools/k8s/reference-definitions/pod-defs/vpp/userspace-dpdk-pod.yaml
@@ -0,0 +1,49 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: userspace-vpp-pod
+ annotations:
+ k8s.v1.cni.cncf.io/networks: userspace-vpp-net, userspace-vpp-net
+spec:
+ containers:
+ - name: vpp-vhost
+ image: newdpdk-app-centos:latest
+ imagePullPolicy: Never
+ securityContext:
+ privileged: true
+ volumeMounts:
+ - mountPath: /etc/podnetinfo
+ name: podinfo
+ readOnly: false
+ - mountPath: /var/lib/cni/usrspcni/
+ name: shared-dir
+ - mountPath: /dev/hugepages
+ name: hugepage
+ resources:
+ requests:
+ cpu: "6000m"
+ memory: "4000Mi"
+ hugepages-1Gi: 4Gi
+ limits:
+ cpu: "6000m"
+ memory: "4000Mi"
+ hugepages-1Gi: 4Gi
+ command: ["sleep", "infinity"]
+ nodeSelector:
+ vswitch: ovs
+ volumes:
+ - name: podinfo
+ downwardAPI:
+ items:
+ - path: "labels"
+ fieldRef:
+ fieldPath: metadata.labels
+ - path: "annotations"
+ fieldRef:
+ fieldPath: metadata.annotations
+ - name: shared-dir
+ hostPath:
+ path: /var/lib/cni/usrspcni/data/
+ - name: hugepage
+ emptyDir:
+ medium: HugePages
diff --git a/tools/k8s/reference-definitions/pod-defs/vpp/userspace-dpdk-pod2.yaml b/tools/k8s/reference-definitions/pod-defs/vpp/userspace-dpdk-pod2.yaml
new file mode 100644
index 00000000..7e3d2e71
--- /dev/null
+++ b/tools/k8s/reference-definitions/pod-defs/vpp/userspace-dpdk-pod2.yaml
@@ -0,0 +1,47 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: userspace-vpp-pod2
+ annotations:
+ k8s.v1.cni.cncf.io/networks: userspace-vpp-net, userspace-vpp-net
+spec:
+ containers:
+ - name: vpp-vhost
+ image: newdpdk-app-centos:latest
+ imagePullPolicy: Never
+ securityContext:
+ privileged: true
+ volumeMounts:
+ - mountPath: /etc/podnetinfo
+ name: podinfo
+ readOnly: false
+ - mountPath: /var/lib/cni/usrspcni/
+ name: shared-dir
+ - mountPath: /dev/hugepages
+ name: hugepage
+ resources:
+ requests:
+ cpu: "6000m"
+ hugepages-1Gi: 4Gi
+ limits:
+ cpu: "6000m"
+ hugepages-1Gi: 4Gi
+ command: ["sleep", "infinity"]
+ nodeSelector:
+ vswitch: ovs
+ volumes:
+ - name: podinfo
+ downwardAPI:
+ items:
+ - path: "labels"
+ fieldRef:
+ fieldPath: metadata.labels
+ - path: "annotations"
+ fieldRef:
+ fieldPath: metadata.annotations
+ - name: shared-dir
+ hostPath:
+ path: /var/lib/cni/usrspcni/data/
+ - name: hugepage
+ emptyDir:
+ medium: HugePages
diff --git a/tools/k8s/test-containers/dpdk-forwarding-pods/Dockerfile b/tools/k8s/test-containers/dpdk-forwarding-pods/Dockerfile
new file mode 100644
index 00000000..58f558fb
--- /dev/null
+++ b/tools/k8s/test-containers/dpdk-forwarding-pods/Dockerfile
@@ -0,0 +1,110 @@
+FROM centos:7
+
+#
+# Install required packages
+#
+RUN rpm --import https://mirror.go-repo.io/centos/RPM-GPG-KEY-GO-REPO && curl -s https://mirror.go-repo.io/centos/go-repo.repo | tee /etc/yum.repos.d/go-repo.repo
+RUN yum groupinstall -y "Development Tools"
+RUN yum install -y wget numactl-devel git golang make; yum clean all
+# Debug Tools (if needed):
+#RUN yum install -y pciutils iproute; yum clean all
+
+#
+# Download and Build APP-NetUtil
+#
+WORKDIR /root/go/src/
+RUN go get github.com/openshift/app-netutil 2>&1 > /tmp/UserspaceDockerBuild.log || echo "Can ignore no GO files."
+WORKDIR /root/go/src/github.com/openshift/app-netutil
+RUN make c_sample
+RUN cp bin/libnetutil_api.so /lib64/libnetutil_api.so; cp bin/libnetutil_api.h /usr/include/libnetutil_api.h
+
+#
+# Download and Build DPDK
+#
+ENV DPDK_VER 20.05
+ENV DPDK_DIR /usr/src/dpdk-${DPDK_VER}
+WORKDIR /usr/src/
+RUN wget http://fast.dpdk.org/rel/dpdk-${DPDK_VER}.tar.xz
+RUN tar -xpvf dpdk-${DPDK_VER}.tar.xz
+
+ENV RTE_TARGET=x86_64-native-linuxapp-gcc
+ENV RTE_SDK=${DPDK_DIR}
+WORKDIR ${DPDK_DIR}
+# DPDK_VER 19.08
+RUN sed -i -e 's/EAL_IGB_UIO=y/EAL_IGB_UIO=n/' config/common_linux
+RUN sed -i -e 's/KNI_KMOD=y/KNI_KMOD=n/' config/common_linux
+RUN sed -i -e 's/LIBRTE_KNI=y/LIBRTE_KNI=n/' config/common_linux
+RUN sed -i -e 's/LIBRTE_PMD_KNI=y/LIBRTE_PMD_KNI=n/' config/common_linux
+# Additional Debug if Needed
+#RUN sed -i -e 's/CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n/CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=y/' config/common_base
+
+# DPDK_VER 19.02
+#RUN sed -i -e 's/EAL_IGB_UIO=y/EAL_IGB_UIO=n/' config/common_linuxapp
+#RUN sed -i -e 's/KNI_KMOD=y/KNI_KMOD=n/' config/common_linuxapp
+#RUN sed -i -e 's/LIBRTE_KNI=y/LIBRTE_KNI=n/' config/common_linuxapp
+#RUN sed -i -e 's/LIBRTE_PMD_KNI=y/LIBRTE_PMD_KNI=n/' config/common_linuxapp
+
+# Add vhost patch
+COPY ./vhost_substitute.sh ./vhost_substitute.sh
+RUN ./vhost_substitute.sh
+
+RUN make install T=${RTE_TARGET} DESTDIR=${RTE_SDK}
+
+#
+# Build TestPmd
+#
+WORKDIR ${DPDK_DIR}/app/test-pmd
+COPY ./dpdk-args.c ./dpdk-args.c
+COPY ./dpdk-args.h ./dpdk-args.h
+COPY ./testpmd_eal_init.txt ./testpmd_eal_init.txt
+COPY ./testpmd_launch_args_parse.txt ./testpmd_launch_args_parse.txt
+COPY ./testpmd_substitute.sh ./testpmd_substitute.sh
+RUN ./testpmd_substitute.sh
+RUN make
+RUN cp testpmd /usr/bin/testpmd
+
+#
+# Build l2fwd
+#
+WORKDIR ${DPDK_DIR}/examples/l2fwd
+COPY ./dpdk-args.c ./dpdk-args.c
+COPY ./dpdk-args.h ./dpdk-args.h
+COPY ./l2fwd_eal_init.txt ./l2fwd_eal_init.txt
+COPY ./l2fwd_parse_args.txt ./l2fwd_parse_args.txt
+COPY ./l2fwd_substitute.sh ./l2fwd_substitute.sh
+RUN ./l2fwd_substitute.sh
+RUN make
+RUN cp build/l2fwd /usr/bin/l2fwd
+
+#
+# Build l3fwd
+#
+#WORKDIR ${DPDK_DIR}/examples/l3fwd
+#COPY ./dpdk-args.c ./dpdk-args.c
+#COPY ./dpdk-args.h ./dpdk-args.h
+#COPY ./l3fwd_eal_init.txt ./l3fwd_eal_init.txt
+#COPY ./l3fwd_parse_args.txt ./l3fwd_parse_args.txt
+#COPY ./l3fwd_substitute.sh ./l3fwd_substitute.sh
+#RUN ./l3fwd_substitute.sh
+#RUN make
+#RUN cp build/l3fwd /usr/bin/l3fwd
+
+# Copy default APP
+RUN cp /usr/bin/l2fwd /usr/bin/dpdk-app
+
+# -------- Import stage.
+# Docker 17.05 or higher
+# BEGIN
+FROM centos
+COPY --from=0 /usr/bin/dpdk-app /usr/bin/dpdk-app
+COPY --from=0 /usr/bin/l2fwd /usr/bin/l2fwd
+#COPY --from=0 /usr/bin/l3fwd /usr/bin/l3fwd
+COPY --from=0 /usr/bin/testpmd /usr/bin/testpmd
+COPY --from=0 /lib64/libnetutil_api.so /lib64/libnetutil_api.so
+COPY --from=0 /usr/lib64/libnuma.so.1 /usr/lib64/libnuma.so.1
+# END
+
+# COPY ./docker-entrypoint.sh /
+# RUN chmod +x /docker-entrypoint.sh
+# ENTRYPOINT ["sleep", "5s"]
+#CMD ["l2fwd"]
diff --git a/tools/k8s/test-containers/trafficgen-pods/pktgen/Dockerfile b/tools/k8s/test-containers/trafficgen-pods/pktgen/Dockerfile
new file mode 100644
index 00000000..8288cf63
--- /dev/null
+++ b/tools/k8s/test-containers/trafficgen-pods/pktgen/Dockerfile
@@ -0,0 +1,48 @@
+FROM centos:7 as builder
+
+#
+## Install required packages
+##
+RUN rpm --import https://mirror.go-repo.io/centos/RPM-GPG-KEY-GO-REPO && curl -s https://mirror.go-repo.io/centos/go-repo.repo | tee /etc/yum.repos.d/go-repo.repo
+RUN yum groupinstall -y "Development Tools"
+RUN yum install -y wget numactl-devel git golang make; yum clean all
+## Debug Tools (if needed):
+RUN yum install -y pciutils iproute; yum clean all
+
+##
+## Download and Build APP-NetUtil
+##
+WORKDIR /root/go/src/
+RUN go get github.com/openshift/app-netutil 2>&1 > /tmp/UserspaceDockerBuild.log || echo "Can ignore no GO files."
+WORKDIR /root/go/src/github.com/openshift/app-netutil
+RUN make c_sample
+RUN cp bin/libnetutil_api.so /lib64/libnetutil_api.so; cp bin/libnetutil_api.h /usr/include/libnetutil_api.h
+
+## Download and Build DPDK
+##
+ENV DPDK_VER 21.02
+ENV DPDK_DIR /usr/src/dpdk-${DPDK_VER}
+WORKDIR /usr/src/
+RUN wget http://fast.dpdk.org/rel/dpdk-${DPDK_VER}.tar.xz
+RUN tar -xpvf dpdk-${DPDK_VER}.tar.xz
+ENV RTE_TARGET=x86_64-native-linuxapp-gcc
+ENV RTE_SDK=${DPDK_DIR}
+WORKDIR ${DPDK_DIR}
+
+COPY ./vhost_substitute.sh ./vhost_substitute.sh
+RUN ./vhost_substitute.sh
+
+RUN yum install -y epel-release && yum install -y dnf
+RUN dnf install -y meson ninja-build
+RUN pip3 install pyelftools
+
+RUN meson build && ninja -C build && ninja -C build install && ldconfig
+
+EXPOSE 22 8474
+
+WORKDIR /usr/src/
+ENV PKG_CONFIG_PATH /usr/local/lib64/pkgconfig
+RUN git clone http://dpdk.org/git/apps/pktgen-dpdk
+RUN yum install -y libpcap libpcap-devel
+RUN cd pktgen-dpdk && make -j
+
diff --git a/tools/pkt_fwd/dummy.py b/tools/pkt_fwd/dummy.py
new file mode 100644
index 00000000..97ffc666
--- /dev/null
+++ b/tools/pkt_fwd/dummy.py
@@ -0,0 +1,62 @@
+# Copyright 2021 Spirent Communications
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""VSPERF Dummy Pkt-Fwd.
+"""
+
+import logging
+from conf import settings
+
+_LOGGER = logging.getLogger(__name__)
+
+class Dummy(IPktFwd):
+ """Dummy implementation
+
+ """
+
+ _logger = logging.getLogger()
+
+ def __init__(self, guest=False):
+ self._logger.info("Initializing Dummy...")
+
+ def start(self):
+ """See IPktFwd for general description
+
+ Activates testpmd.
+ """
+ self._logger.info("Starting Dummy...")
+
+ def start_for_guest(self):
+ """See IPktFwd for general description
+
+ Activates testpmd for guest config
+ """
+ self._logger.info("Starting Dummy for one guest...")
+
+ def stop(self):
+ """See IPktFwd for general description
+
+ Kills testpmd.
+ """
+ self._logger.info("Stopping Dummy ....")
+
+ # Method could be a function
+ # pylint: disable=no-self-use
+ def get_version(self):
+ """
+ Get product version
+ :return: None
+ """
+ # No way to read Dummy version
+ return []