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
-rw-r--r--testcases/testcase.py12
-rw-r--r--tools/extvswitchflctl.py129
-rw-r--r--tools/pkt_fwd/dummy.py62
8 files changed, 256 insertions, 14 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/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/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 []