aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/component_factory.py50
-rwxr-xr-xcore/loader/loader.py37
-rw-r--r--core/loader/loader_servant.py4
-rw-r--r--core/pktfwd_controller.py16
-rw-r--r--core/pod_controller.py93
-rw-r--r--core/results/results_constants.py9
-rw-r--r--core/traffic_controller.py9
-rw-r--r--core/traffic_controller_rfc2544.py5
-rw-r--r--core/traffic_controller_rfc2889.py2
-rw-r--r--core/vnf_controller.py3
-rw-r--r--core/vswitch_controller.py44
-rw-r--r--core/vswitch_controller_clean.py34
-rw-r--r--core/vswitch_controller_op2p.py66
-rw-r--r--core/vswitch_controller_p2p.py139
-rw-r--r--core/vswitch_controller_ptunp.py68
-rw-r--r--core/vswitch_controller_pxp.py142
16 files changed, 331 insertions, 390 deletions
diff --git a/core/component_factory.py b/core/component_factory.py
index bd9a1019..f13bfb5b 100644
--- a/core/component_factory.py
+++ b/core/component_factory.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2017 Intel Corporation.
+# Copyright 2015-2018 Intel Corporation., Tieto
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ from core.vswitch_controller_op2p import VswitchControllerOP2P
from core.vswitch_controller_ptunp import VswitchControllerPtunP
from core.vnf_controller import VnfController
from core.pktfwd_controller import PktFwdController
-
+from core.pod_controller import PodController
def __init__():
"""Finds and loads all the modules required.
@@ -66,23 +66,23 @@ def create_vswitch(deployment_scenario, vswitch_class, traffic,
:return: IVSwitchController for the deployment_scenario
"""
# pylint: disable=too-many-return-statements
- deployment_scenario = deployment_scenario.lower()
- if deployment_scenario.startswith("p2p"):
- return VswitchControllerP2P(vswitch_class, traffic)
- elif deployment_scenario.startswith("pvp"):
- return VswitchControllerPXP(deployment_scenario, vswitch_class, traffic)
- elif deployment_scenario.startswith("pvvp"):
- return VswitchControllerPXP(deployment_scenario, vswitch_class, traffic)
- elif deployment_scenario.startswith("pvpv"):
- return VswitchControllerPXP(deployment_scenario, vswitch_class, traffic)
- elif deployment_scenario.startswith("op2p"):
- return VswitchControllerOP2P(vswitch_class, traffic, tunnel_operation)
- elif deployment_scenario.startswith("ptunp"):
- return VswitchControllerPtunP(vswitch_class, traffic)
- elif deployment_scenario.startswith("clean"):
- return VswitchControllerClean(vswitch_class, traffic)
+ deployment = deployment_scenario.lower()
+ if deployment.startswith("p2p"):
+ return VswitchControllerP2P(deployment, vswitch_class, traffic)
+ elif deployment.startswith("pvp"):
+ return VswitchControllerPXP(deployment, vswitch_class, traffic)
+ elif deployment.startswith("pvvp"):
+ return VswitchControllerPXP(deployment, vswitch_class, traffic)
+ elif deployment.startswith("pvpv"):
+ return VswitchControllerPXP(deployment, vswitch_class, traffic)
+ elif deployment.startswith("op2p"):
+ return VswitchControllerOP2P(deployment, vswitch_class, traffic, tunnel_operation)
+ elif deployment.startswith("ptunp"):
+ return VswitchControllerPtunP(deployment, vswitch_class, traffic)
+ elif deployment.startswith("clean"):
+ return VswitchControllerClean(deployment, vswitch_class, traffic)
else:
- raise RuntimeError("Unknown deployment scenario '{}'.".format(deployment_scenario))
+ raise RuntimeError("Unknown deployment scenario '{}'.".format(deployment))
def create_vnf(deployment_scenario, vnf_class, extra_vnfs):
@@ -102,6 +102,19 @@ def create_vnf(deployment_scenario, vnf_class, extra_vnfs):
"""
return VnfController(deployment_scenario, vnf_class, extra_vnfs)
+def create_pod(deployment_scenario, pod_class):
+ """Return a new PodController for the deployment_scenario.
+
+ The returned controller is configured with the given POD class.
+
+ Deployment scenarios: 'pvp', 'pvvp'
+
+ :param deployment_scenario: The deployment scenario name
+ :param pod_class: Reference to pod class to be used.
+ :return: PodController for the deployment_scenario
+ """
+ return PodController(deployment_scenario, pod_class)
+
def create_collector(collector_class, result_dir, test_name):
"""Return a new Collector of the given class
@@ -121,7 +134,6 @@ def create_loadgen(loadgen_class, loadgen_cfg):
:param loadgen_cfg: Configuration for the loadgen
:return: A new ILoadGenerator class
"""
- # pylint: disable=too-many-function-args
return loadgen_class(loadgen_cfg)
def create_pktfwd(deployment, pktfwd_class):
diff --git a/core/loader/loader.py b/core/loader/loader.py
index dcd77ced..45e0d5ba 100755
--- a/core/loader/loader.py
+++ b/core/loader/loader.py
@@ -23,6 +23,7 @@ from tools.pkt_fwd.pkt_fwd import IPktFwd
from tools.pkt_gen.trafficgen import ITrafficGenerator
from vswitches.vswitch import IVSwitch
from vnfs.vnf.vnf import IVnf
+from pods.pod.pod import IPod
# pylint: disable=too-many-public-methods
class Loader(object):
@@ -71,6 +72,11 @@ class Loader(object):
settings.getValue('PKTFWD'),
IPktFwd)
+ self._pod_loader = LoaderServant(
+ settings.getValue('POD_DIR'),
+ settings.getValue('POD'),
+ IPod)
+
def get_trafficgen(self):
"""Returns a new instance configured traffic generator.
@@ -220,6 +226,37 @@ class Loader(object):
"""
return self._vnf_loader.get_classes_printable()
+ def get_pod(self):
+ """Returns instance of currently configured pod implementation.
+
+ :return: IPod implementation if available, None otherwise.
+ """
+ return self._pod_loader.get_class()()
+
+ def get_pod_class(self):
+ """Returns type of currently configured pod implementation.
+
+ :return: Type of IPod implementation if available.
+ None otherwise.
+ """
+ return self._pod_loader.get_class()
+
+ def get_pods(self):
+ """Returns dictionary of all available pods.
+
+ :return: Dictionary of pods.
+ - key: name of the class which implements IPod,
+ - value: Type of vnf which implements IPod.
+ """
+ return self._pod_loader.get_classes()
+
+ def get_pods_printable(self):
+ """Returns all available pods in printable format.
+
+ :return: String containing printable list of pods.
+ """
+ return self._pod_loader.get_classes_printable()
+
def get_pktfwd(self):
"""Returns instance of currently configured packet forwarder implementation.
diff --git a/core/loader/loader_servant.py b/core/loader/loader_servant.py
index 8bad9ab9..6db8e0f2 100644
--- a/core/loader/loader_servant.py
+++ b/core/loader/loader_servant.py
@@ -120,7 +120,7 @@ class LoaderServant(object):
if class_name in results:
logging.info(
- "Class found: " + class_name + ".")
+ "Class found: %s.", class_name)
return results.get(class_name)
return None
@@ -180,7 +180,7 @@ class LoaderServant(object):
mod = imp.load_module(
modname, *imp.find_module(modname, [root]))
except ImportError:
- logging.error('Could not import file ' + filename)
+ logging.error('Could not import file %s', filename)
raise
mods.append((modname, mod))
diff --git a/core/pktfwd_controller.py b/core/pktfwd_controller.py
index b38aefa5..363302c3 100644
--- a/core/pktfwd_controller.py
+++ b/core/pktfwd_controller.py
@@ -1,4 +1,4 @@
-# Copyright 2016 Intel Corporation.
+# Copyright 2016-2018 Intel Corporation., Tieto
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -35,12 +35,12 @@ class PktFwdController(object):
self._pktfwd_class = pktfwd_class
self._pktfwd = pktfwd_class(guest=True if deployment == "pvp" and
settings.getValue('VNF') != "QemuPciPassthrough" else False)
- self._logger.debug('Creation using ' + str(self._pktfwd_class))
+ self._logger.debug('Creation using %s', str(self._pktfwd_class))
def setup(self):
"""Sets up the packet forwarder for p2p.
"""
- self._logger.debug('Setup using ' + str(self._pktfwd_class))
+ self._logger.debug('Setup using %s', str(self._pktfwd_class))
try:
self._pktfwd.start()
@@ -56,7 +56,7 @@ class PktFwdController(object):
def setup_for_guest(self):
"""Sets up the packet forwarder for pvp.
"""
- self._logger.debug('Setup using ' + str(self._pktfwd_class))
+ self._logger.debug('Setup using %s', str(self._pktfwd_class))
try:
self._pktfwd.start_for_guest()
@@ -67,7 +67,7 @@ class PktFwdController(object):
def stop(self):
"""Tears down the packet forwarder created in setup().
"""
- self._logger.debug('Stop using ' + str(self._pktfwd_class))
+ self._logger.debug('Stop using %s', str(self._pktfwd_class))
self._pktfwd.stop()
def __enter__(self):
@@ -89,9 +89,9 @@ class PktFwdController(object):
"""
return self._pktfwd
- def dump_vswitch_flows(self):
- """ Dumps flows from vswitch
+ def dump_vswitch_connections(self):
+ """ Dumps connections from vswitch
"""
raise NotImplementedError(
"The PktFwdController does not implement the "
- "\"dump_vswitch_flows\" function.")
+ "\"dump_vswitch_connections\" function.")
diff --git a/core/pod_controller.py b/core/pod_controller.py
new file mode 100644
index 00000000..8bc91ec4
--- /dev/null
+++ b/core/pod_controller.py
@@ -0,0 +1,93 @@
+# Copyright 2020 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.
+""" pod Controller interface
+"""
+
+import logging
+import pexpect
+#from conf import settings
+from pods.pod.pod import IPod
+
+class PodController():
+ """POD controller class
+
+ Used to set-up and control PODs for specified scenario
+
+ Attributes:
+ _pod_class: A class object representing the POD.
+ _deployment: A string describing the scenario to set-up in the
+ constructor.
+ _pods: A list of pods controlled by the controller.
+ """
+
+ def __init__(self, deployment, pod_class):
+ """Sets up the POD infrastructure based on deployment scenario
+
+ :param pod_class: The POD class to be used.
+ """
+ # reset POD ID counter for each testcase
+ IPod.reset_pod_counter()
+ pod_number = 0
+ # setup controller with requested number of pods
+ self._logger = logging.getLogger(__name__)
+ self._pod_class = pod_class
+ self._deployment = deployment.lower()
+ self._pods = []
+ if self._deployment == 'p2p':
+ pod_number = 1
+
+ if pod_number:
+ self._pods = [pod_class() for _ in range(pod_number)]
+
+ self._logger.debug('Initializing the pod')
+
+ def get_pods(self):
+ """Returns a list of pods controlled by this controller.
+ """
+ self._logger.debug('get the pods')
+ return self._pods
+
+ def get_pods_number(self):
+ """Returns a number of pods controlled by this controller.
+ """
+ self._logger.debug('get_pods_number %s pod[s]', str(len(self._pods)))
+ return len(self._pods)
+
+ def start(self):
+ """Boots all pods set-up by __init__.
+
+ This is a blocking function.
+ """
+ self._logger.debug('start the pod')
+ try:
+ for pod in self._pods:
+ pod.create()
+ except pexpect.TIMEOUT:
+ self.stop()
+ raise
+
+ def stop(self):
+ """Stops all pods set-up by __init__.
+
+ This is a blocking function.
+ """
+ self._logger.debug('stopping the pod')
+ for pod in self._pods:
+ pod.terminate()
+
+ def __enter__(self):
+ self.start()
+
+ def __exit__(self, type_, value, traceback):
+ self.stop()
diff --git a/core/results/results_constants.py b/core/results/results_constants.py
index 967adbf9..769938a8 100644
--- a/core/results/results_constants.py
+++ b/core/results/results_constants.py
@@ -73,6 +73,11 @@ class ResultsConstants(object):
CAPTURE_TX = "capture_tx"
CAPTURE_RX = "capture_rx"
+ # IMIX Used
+ IMIX_GENOME = "imix_genome"
+ # IMIX Avg. Frame Size
+ IMIX_AVG_FRAMESIZE = "imix_avg_framesize"
+
@staticmethod
def get_traffic_constants():
"""Method returns all Constants used to store results.
@@ -96,4 +101,6 @@ class ResultsConstants(object):
ResultsConstants.MIN_LATENCY_NS,
ResultsConstants.MAX_LATENCY_NS,
ResultsConstants.AVG_LATENCY_NS,
- ResultsConstants.FRAME_LOSS_PERCENT]
+ ResultsConstants.FRAME_LOSS_PERCENT,
+ ResultsConstants.IMIX_GENOME,
+ ResultsConstants.IMIX_AVG_FRAMESIZE]
diff --git a/core/traffic_controller.py b/core/traffic_controller.py
index de82dddf..1f21e57d 100644
--- a/core/traffic_controller.py
+++ b/core/traffic_controller.py
@@ -125,7 +125,7 @@ class TrafficController(object):
:param traffic: A dictionary describing the traffic to send.
"""
- self._logger.debug('send_traffic with ' +
+ self._logger.debug('send_traffic with %s',
str(self._traffic_gen_class))
self.configure(traffic)
@@ -144,7 +144,8 @@ class TrafficController(object):
If this function requires more than one argument, all should be
should be passed using the args list and appropriately handled.
"""
- self._logger.debug('send_traffic_async with ' +
+ # pylint: disable=unused-argument
+ self._logger.debug('send_traffic_async with %s',
str(self._traffic_gen_class))
self.configure(traffic)
@@ -158,7 +159,7 @@ class TrafficController(object):
"""
counter = 0
for item in self._results:
- logging.info("Record: " + str(counter))
+ logging.info("Record: %s", str(counter))
counter += 1
for(key, value) in list(item.items()):
logging.info(" Key: " + str(key) +
@@ -169,7 +170,7 @@ class TrafficController(object):
"""
return self._results
- def validate_send_traffic(self, dummy_result, dummy_traffic):
+ def validate_send_traffic(self, _dummy_result, _dummy_traffic):
"""Verify that send traffic has succeeded
"""
if self._results:
diff --git a/core/traffic_controller_rfc2544.py b/core/traffic_controller_rfc2544.py
index 488dde6f..2bb30fec 100644
--- a/core/traffic_controller_rfc2544.py
+++ b/core/traffic_controller_rfc2544.py
@@ -62,6 +62,9 @@ class TrafficControllerRFC2544(TrafficController, IResults):
elif traffic['traffic_type'] == 'rfc2544_continuous':
result = self._traffic_gen_class.send_cont_traffic(
traffic, duration=self._duration)
+ elif traffic['traffic_type'] == 'burst':
+ result = self._traffic_gen_class.send_burst_traffic(
+ traffic, duration=self._duration)
elif traffic['traffic_type'] == 'rfc2544_throughput':
result = self._traffic_gen_class.send_rfc2544_throughput(
traffic, tests=self._tests, duration=self._duration, lossrate=self._lossrate)
@@ -87,7 +90,7 @@ class TrafficControllerRFC2544(TrafficController, IResults):
tests=self._tests,
duration=self._duration)
self._traffic_started = True
- if len(function['args']) > 0:
+ if function['args']:
function['function'](function['args'])
else:
function['function']()
diff --git a/core/traffic_controller_rfc2889.py b/core/traffic_controller_rfc2889.py
index 64ab0ba6..316202c9 100644
--- a/core/traffic_controller_rfc2889.py
+++ b/core/traffic_controller_rfc2889.py
@@ -84,7 +84,7 @@ class TrafficControllerRFC2889(TrafficController, IResults):
trials=self._trials,
duration=self._duration)
self._traffic_started = True
- if len(function['args']) > 0:
+ if function['args']:
function['function'](function['args'])
else:
function['function']()
diff --git a/core/vnf_controller.py b/core/vnf_controller.py
index 78a29258..cbf59b79 100644
--- a/core/vnf_controller.py
+++ b/core/vnf_controller.py
@@ -93,8 +93,7 @@ class VnfController(object):
def get_vnfs_number(self):
"""Returns a number of vnfs controlled by this controller.
"""
- self._logger.debug('get_vnfs_number ' + str(len(self._vnfs)) +
- ' VNF[s]')
+ self._logger.debug('get_vnfs_number %s VNF[s]', str(len(self._vnfs)))
return len(self._vnfs)
def start(self):
diff --git a/core/vswitch_controller.py b/core/vswitch_controller.py
index 855de8b2..889f14bc 100644
--- a/core/vswitch_controller.py
+++ b/core/vswitch_controller.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Intel Corporation.
+# Copyright 2015-2018 Intel Corporation., Tieto
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,33 +13,57 @@
# limitations under the License.
"""Interface for deployment specific vSwitch controllers
"""
+import logging
class IVswitchController(object):
- """Abstract class which defines a vSwitch controller object
+ """Interface class for a vSwitch controller object
This interface is used to setup and control a vSwitch provider for a
particular deployment scenario.
"""
- def __enter__(self):
+ def __init__(self, deployment, vswitch_class, traffic):
+ """Initializes up the generic prerequisites for deployment scenario.
+
+ :deployment: the deployment scenario to configure
+ :vswitch_class: the vSwitch class to be used.
+ :traffic: dictionary with detailed traffic definition
+ """
+ self._logger = logging.getLogger(__name__)
+ self._vswitch_class = vswitch_class
+ self._vswitch = vswitch_class()
+ self._deployment_scenario = deployment
+ self._logger.debug('Creation using %s', str(self._vswitch_class))
+ self._traffic = traffic.copy()
+ self._bridge = None
+
+ def setup(self):
"""Sets up the switch for the particular deployment scenario
"""
raise NotImplementedError(
"The VswitchController does not implement the \"setup\" function.")
- def __exit__(self, type_, value, traceback):
+ def stop(self):
"""Tears down the switch created in setup()
"""
raise NotImplementedError(
"The VswitchController does not implement the \"stop\" function.")
+ def __enter__(self):
+ """Sets up the switch for the particular deployment scenario
+ """
+ self.setup()
+
+ def __exit__(self, type_, value, traceback):
+ """Tears down the switch created in setup()
+ """
+ self.stop()
+
def get_vswitch(self):
"""Get the controlled vSwitch
:return: The controlled IVswitch
"""
- raise NotImplementedError(
- "The VswitchController does not implement the \"get_vswitch\" "
- "function.")
+ return self._vswitch
def get_ports_info(self):
"""Returns a dictionary describing all ports on the vSwitch.
@@ -50,9 +74,9 @@ class IVswitchController(object):
"The VswitchController does not implement the \"get_ports_info\" "
"function.")
- def dump_vswitch_flows(self):
- """ Dumps flows from vswitch
+ def dump_vswitch_connections(self):
+ """ Dumps connections from vswitch
"""
raise NotImplementedError(
"The VswitchController does not implement the "
- "\"dump_vswitch_flows\" function.")
+ "\"dump_vswitch_connections\" function.")
diff --git a/core/vswitch_controller_clean.py b/core/vswitch_controller_clean.py
index 61724b9b..7a771226 100644
--- a/core/vswitch_controller_clean.py
+++ b/core/vswitch_controller_clean.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016 Intel Corporation.
+# Copyright 2015-2018 Intel Corporation., Tieto
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,9 +14,6 @@
"""VSwitch controller for basic initialization of vswitch
"""
-
-import logging
-
from core.vswitch_controller import IVswitchController
class VswitchControllerClean(IVswitchController):
@@ -28,22 +25,10 @@ class VswitchControllerClean(IVswitchController):
_deployment_scenario: A string describing the scenario to set-up in the
constructor.
"""
- def __init__(self, vswitch_class, traffic):
- """Initializes up the prerequisites for the Clean deployment scenario.
-
- :vswitch_class: the vSwitch class to be used.
- """
- self._logger = logging.getLogger(__name__)
- self._vswitch_class = vswitch_class
- self._vswitch = vswitch_class()
- self._deployment_scenario = "Clean"
- self._logger.debug('Creation using ' + str(self._vswitch_class))
- self._traffic = traffic.copy()
-
def setup(self):
"""Sets up the switch for Clean.
"""
- self._logger.debug('Setup using ' + str(self._vswitch_class))
+ self._logger.debug('Setup using %s', str(self._vswitch_class))
try:
self._vswitch.start()
@@ -54,26 +39,15 @@ class VswitchControllerClean(IVswitchController):
def stop(self):
"""Tears down the switch created in setup().
"""
- self._logger.debug('Stop using ' + str(self._vswitch_class))
+ self._logger.debug('Stop using %s', str(self._vswitch_class))
self._vswitch.stop()
- def __enter__(self):
- self.setup()
-
- def __exit__(self, type_, value, traceback):
- self.stop()
-
- def get_vswitch(self):
- """See IVswitchController for description
- """
- return self._vswitch
-
def get_ports_info(self):
"""See IVswitchController for description
"""
pass
- def dump_vswitch_flows(self):
+ def dump_vswitch_connections(self):
"""See IVswitchController for description
"""
pass
diff --git a/core/vswitch_controller_op2p.py b/core/vswitch_controller_op2p.py
index 85bf79bd..072a690a 100644
--- a/core/vswitch_controller_op2p.py
+++ b/core/vswitch_controller_op2p.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2017 Intel Corporation.
+# Copyright 2015-2018 Intel Corporation., Tieto
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,44 +14,24 @@
"""VSwitch controller for Physical to Tunnel Endpoint to Physical deployment
"""
-
-import logging
-
from core.vswitch_controller import IVswitchController
from vswitches.utils import add_ports_to_flow
from conf import settings as S
from tools import tasks
-_FLOW_TEMPLATE = {
- 'idle_timeout': '0'
-}
-
class VswitchControllerOP2P(IVswitchController):
"""VSwitch controller for OP2P deployment scenario.
-
- Attributes:
- _vswitch_class: The vSwitch class to be used.
- _vswitch: The vSwitch object controlled by this controller
- _deployment_scenario: A string describing the scenario to set-up in the
- constructor.
"""
- def __init__(self, vswitch_class, traffic, tunnel_operation=None):
- """Initializes up the prerequisites for the OP2P deployment scenario.
-
- :vswitch_class: the vSwitch class to be used.
+ def __init__(self, deployment, vswitch_class, traffic, tunnel_operation=None):
+ """See IVswitchController for general description
"""
- self._logger = logging.getLogger(__name__)
- self._vswitch_class = vswitch_class
- self._vswitch = vswitch_class()
- self._deployment_scenario = "OP2P"
- self._traffic = traffic.copy()
+ super().__init__(deployment, vswitch_class, traffic)
self._tunnel_operation = tunnel_operation
- self._logger.debug('Creation using ' + str(self._vswitch_class))
def setup(self):
""" Sets up the switch for overlay P2P (tunnel encap or decap)
"""
- self._logger.debug('Setting up ' + str(self._tunnel_operation))
+ self._logger.debug('Setting up %s', str(self._tunnel_operation))
if self._tunnel_operation == "encapsulation":
self._setup_encap()
else:
@@ -66,7 +46,7 @@ class VswitchControllerOP2P(IVswitchController):
Create 2 bridges br0 (integration bridge) and br-ext and a VXLAN port
for encapsulation.
"""
- self._logger.debug('Setup using ' + str(self._vswitch_class))
+ self._logger.debug('Setup using %s', str(self._vswitch_class))
try:
self._vswitch.start()
@@ -118,10 +98,13 @@ class VswitchControllerOP2P(IVswitchController):
# Test is unidirectional for now
self._vswitch.del_flow(bridge)
- flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number,
+ flow1 = add_ports_to_flow(S.getValue('OVS_FLOW_TEMPLATE'), phy1_number,
phy2_number)
self._vswitch.add_flow(bridge, flow1)
-
+ # enable MAC learning mode at external bridge
+ flow_ext = S.getValue('OVS_FLOW_TEMPLATE').copy()
+ flow_ext.update({'actions': ['NORMAL']})
+ self._vswitch.add_flow(bridge_ext, flow_ext)
except:
self._vswitch.stop()
raise
@@ -129,7 +112,7 @@ class VswitchControllerOP2P(IVswitchController):
def _setup_decap(self):
""" Sets up the switch for overlay P2P decapsulation test
"""
- self._logger.debug('Setup using ' + str(self._vswitch_class))
+ self._logger.debug('Setup using %s', str(self._vswitch_class))
try:
self._vswitch.start()
@@ -178,7 +161,7 @@ class VswitchControllerOP2P(IVswitchController):
bridge)
# Test is unidirectional for now
self._vswitch.del_flow(bridge_ext)
- flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy3_number,
+ flow1 = add_ports_to_flow(S.getValue('OVS_FLOW_TEMPLATE'), phy3_number,
phy2_number)
self._vswitch.add_flow(bridge_ext, flow1)
@@ -189,7 +172,7 @@ class VswitchControllerOP2P(IVswitchController):
def _setup_decap_vanilla(self):
""" Sets up the switch for overlay P2P decapsulation test
"""
- self._logger.debug('Setup decap vanilla ' + str(self._vswitch_class))
+ self._logger.debug('Setup decap vanilla %s', str(self._vswitch_class))
try:
self._vswitch.start()
@@ -251,7 +234,7 @@ class VswitchControllerOP2P(IVswitchController):
# Test is unidirectional for now
self._vswitch.del_flow(bridge_ext)
- flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number, 'LOCAL')
+ flow1 = add_ports_to_flow(S.getValue('OVS_FLOW_TEMPLATE'), phy2_number, 'LOCAL')
self._vswitch.add_flow(bridge_ext, flow1)
except:
@@ -261,20 +244,9 @@ class VswitchControllerOP2P(IVswitchController):
def stop(self):
"""Tears down the switch created in setup().
"""
- self._logger.debug('Stop using ' + str(self._vswitch_class))
+ self._logger.debug('Stop using %s', str(self._vswitch_class))
self._vswitch.stop()
- def __enter__(self):
- self.setup()
-
- def __exit__(self, type_, value, traceback):
- self.stop()
-
- def get_vswitch(self):
- """See IVswitchController for description
- """
- return self._vswitch
-
def get_ports_info(self):
"""See IVswitchController for description
"""
@@ -286,8 +258,8 @@ class VswitchControllerOP2P(IVswitchController):
self._vswitch.get_ports(
S.getValue('TUNNEL_EXTERNAL_BRIDGE'))
- def dump_vswitch_flows(self):
+ def dump_vswitch_connections(self):
"""See IVswitchController for description
"""
- self._vswitch.dump_flows(S.getValue('TUNNEL_INTEGRATION_BRIDGE'))
- self._vswitch.dump_flows(S.getValue('TUNNEL_EXTERNAL_BRIDGE'))
+ self._vswitch.dump_connections(S.getValue('TUNNEL_INTEGRATION_BRIDGE'))
+ self._vswitch.dump_connections(S.getValue('TUNNEL_EXTERNAL_BRIDGE'))
diff --git a/core/vswitch_controller_p2p.py b/core/vswitch_controller_p2p.py
index 0d41b145..0037d484 100644
--- a/core/vswitch_controller_p2p.py
+++ b/core/vswitch_controller_p2p.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2017 Intel Corporation.
+# Copyright 2015-2018 Intel Corporation., Tieto
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,20 +14,9 @@
"""VSwitch controller for Physical to Physical deployment
"""
-
-import logging
-import netaddr
-
from core.vswitch_controller import IVswitchController
from conf import settings
-_FLOW_TEMPLATE = {
- 'idle_timeout': '0'
-}
-
-_PROTO_TCP = 6
-_PROTO_UDP = 17
-
class VswitchControllerP2P(IVswitchController):
"""VSwitch controller for P2P deployment scenario.
@@ -37,71 +26,29 @@ class VswitchControllerP2P(IVswitchController):
_deployment_scenario: A string describing the scenario to set-up in the
constructor.
"""
- def __init__(self, vswitch_class, traffic):
- """Initializes up the prerequisites for the P2P deployment scenario.
-
- :vswitch_class: the vSwitch class to be used.
+ def __init__(self, deployment, vswitch_class, traffic):
+ """See IVswitchController for general description
"""
- self._logger = logging.getLogger(__name__)
- self._vswitch_class = vswitch_class
- self._vswitch = vswitch_class()
- self._deployment_scenario = "P2P"
- self._logger.debug('Creation using ' + str(self._vswitch_class))
- self._traffic = traffic.copy()
+ super().__init__(deployment, vswitch_class, traffic)
+ self._bridge = settings.getValue('VSWITCH_BRIDGE_NAME')
def setup(self):
"""Sets up the switch for p2p.
"""
- self._logger.debug('Setup using ' + str(self._vswitch_class))
+ self._logger.debug('Setup using %s', str(self._vswitch_class))
try:
self._vswitch.start()
- bridge = settings.getValue('VSWITCH_BRIDGE_NAME')
- self._vswitch.add_switch(bridge)
-
- (_, _) = self._vswitch.add_phy_port(bridge)
- (_, _) = self._vswitch.add_phy_port(bridge)
-
- self._vswitch.del_flow(bridge)
-
- # table#0 - flows designed to force 5 & 13 tuple matches go here
- flow = {'table':'0', 'priority':'1', 'actions': ['goto_table:1']}
- self._vswitch.add_flow(bridge, flow)
-
- # table#1 - flows to route packets between ports goes here. The
- # chosen port is communicated to subsequent tables by setting the
- # metadata value to the egress port number
+ self._vswitch.add_switch(self._bridge)
- # configure flows according to the TC definition
- flow_template = _FLOW_TEMPLATE.copy()
- if self._traffic['flow_type'] == 'IP':
- flow_template.update({'dl_type':'0x0800', 'nw_src':self._traffic['l3']['srcip'],
- 'nw_dst':self._traffic['l3']['dstip']})
+ (port1, _) = self._vswitch.add_phy_port(self._bridge)
+ (port2, _) = self._vswitch.add_phy_port(self._bridge)
- flow = flow_template.copy()
- flow.update({'table':'1', 'priority':'1', 'in_port':'1',
- 'actions': ['write_actions(output:2)', 'write_metadata:0x2',
- 'goto_table:2']})
- self.process_flow_template(bridge, flow)
- flow = flow_template.copy()
- flow.update({'table':'1', 'priority':'1', 'in_port':'2',
- 'actions': ['write_actions(output:1)', 'write_metadata:0x1',
- 'goto_table:2']})
- self.process_flow_template(bridge, flow)
+ if not settings.getValue('K8S'):
+ self._vswitch.add_connection(self._bridge, port1, port2, self._traffic)
+ self._vswitch.add_connection(self._bridge, port2, port1, self._traffic)
- # Frame modification table. Frame modification flow rules are
- # isolated in this table so that they can be turned on or off
- # without affecting the routing or tuple-matching flow rules.
- flow = {'table':'2', 'priority':'1', 'actions': ['goto_table:3']}
- self._vswitch.add_flow(bridge, flow)
-
- # Egress table
- # (TODO) Billy O'Mahony - the drop action here actually required in
- # order to egress the packet. This is the subject of a thread on
- # ovs-discuss 2015-06-30.
- flow = {'table':'3', 'priority':'1', 'actions': ['drop']}
- self._vswitch.add_flow(bridge, flow)
except:
self._vswitch.stop()
raise
@@ -109,68 +56,16 @@ class VswitchControllerP2P(IVswitchController):
def stop(self):
"""Tears down the switch created in setup().
"""
- self._logger.debug('Stop using ' + str(self._vswitch_class))
+ self._logger.debug('Stop using %s', str(self._vswitch_class))
self._vswitch.stop()
- def __enter__(self):
- self.setup()
-
- def __exit__(self, type_, value, traceback):
- self.stop()
-
- def get_vswitch(self):
- """See IVswitchController for description
- """
- return self._vswitch
-
def get_ports_info(self):
"""See IVswitchController for description
"""
- self._logger.debug('get_ports_info using ' + str(self._vswitch_class))
- return self._vswitch.get_ports(settings.getValue('VSWITCH_BRIDGE_NAME'))
+ self._logger.debug('get_ports_info using %s', str(self._vswitch_class))
+ return self._vswitch.get_ports(self._bridge)
- def dump_vswitch_flows(self):
+ def dump_vswitch_connections(self):
"""See IVswitchController for description
"""
- self._vswitch.dump_flows(settings.getValue('VSWITCH_BRIDGE_NAME'))
-
- def process_flow_template(self, bridge, flow_template):
- """Method adds flows into the vswitch based on given flow template
- and configuration of multistream feature.
- """
- if ('pre_installed_flows' in self._traffic and
- self._traffic['pre_installed_flows'].lower() == 'yes' and
- 'multistream' in self._traffic and self._traffic['multistream'] > 0 and
- 'stream_type' in self._traffic):
- # multistream feature is enabled and flows should be inserted into OVS
- # so generate flows based on template and multistream configuration
- if self._traffic['stream_type'] == 'L2':
- # iterate through destimation MAC address
- dst_mac_value = netaddr.EUI(self._traffic['l2']['dstmac']).value
- for i in range(self._traffic['multistream']):
- tmp_mac = netaddr.EUI(dst_mac_value + i)
- tmp_mac.dialect = netaddr.mac_unix_expanded
- flow_template.update({'dl_dst':tmp_mac})
- # optimize flow insertion by usage of cache
- self._vswitch.add_flow(bridge, flow_template, cache='on')
- elif self._traffic['stream_type'] == 'L3':
- # iterate through destimation IP address
- dst_ip_value = netaddr.IPAddress(self._traffic['l3']['dstip']).value
- for i in range(self._traffic['multistream']):
- tmp_ip = netaddr.IPAddress(dst_ip_value + i)
- flow_template.update({'dl_type':'0x0800', 'nw_dst':tmp_ip})
- # optimize flow insertion by usage of cache
- self._vswitch.add_flow(bridge, flow_template, cache='on')
- elif self._traffic['stream_type'] == 'L4':
- # read transport protocol from configuration and iterate through its destination port
- proto = _PROTO_TCP if self._traffic['l3']['proto'].lower() == 'tcp' else _PROTO_UDP
- for i in range(self._traffic['multistream']):
- flow_template.update({'dl_type':'0x0800', 'nw_proto':proto, 'tp_dst':i})
- # optimize flow insertion by usage of cache
- self._vswitch.add_flow(bridge, flow_template, cache='on')
- else:
- self._logger.error('Stream type is set to uknown value %s', self._traffic['stream_type'])
- # insert cached flows into the OVS
- self._vswitch.add_flow(bridge, [], cache='flush')
- else:
- self._vswitch.add_flow(bridge, flow_template)
+ self._vswitch.dump_connections(self._bridge)
diff --git a/core/vswitch_controller_ptunp.py b/core/vswitch_controller_ptunp.py
index 27d26789..b10da2a9 100644
--- a/core/vswitch_controller_ptunp.py
+++ b/core/vswitch_controller_ptunp.py
@@ -1,4 +1,4 @@
-# Copyright 2015-2016 Intel Corporation.
+# Copyright 2015-2018 Intel Corporation., Tieto
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
"""VSwitch controller for Physical to VxLAN Tunnel Endpoint to Physical
deployment with mod operation.
"""
-
-import logging
from netaddr import EUI, IPNetwork, mac_unix
from core.vswitch_controller import IVswitchController
@@ -24,10 +22,6 @@ from vswitches.utils import add_ports_to_flow
from conf import settings
from tools import tasks
-_FLOW_TEMPLATE = {
- 'idle_timeout': '0'
-}
-
class VswitchControllerPtunP(IVswitchController):
"""VSwitch controller for VxLAN ptunp deployment scenario.
The deployment scenario is to test VxLAN tunneling feature without using an
@@ -40,16 +34,10 @@ class VswitchControllerPtunP(IVswitchController):
_deployment_scenario: A string describing the scenario to set-up in the
constructor.
"""
- def __init__(self, vswitch_class, traffic):
- """Initializes up the prerequisites for the ptunp deployment scenario.
-
- :vswitch_class: the vSwitch class to be used.
+ def __init__(self, deployment, vswitch_class, traffic):
+ """See IVswitchController for general description
"""
- self._logger = logging.getLogger(__name__)
- self._vswitch_class = vswitch_class
- self._vswitch = vswitch_class()
- self._deployment_scenario = "ptunp"
- self._traffic = traffic.copy()
+ super().__init__(deployment, vswitch_class, traffic)
self.bridge_phy1 = settings.getValue('TUNNEL_EXTERNAL_BRIDGE1')
self.bridge_phy2 = settings.getValue('TUNNEL_EXTERNAL_BRIDGE2')
self.bridge_mod1 = settings.getValue('TUNNEL_MODIFY_BRIDGE1')
@@ -59,13 +47,12 @@ class VswitchControllerPtunP(IVswitchController):
self.br_mod_ip1 = settings.getValue('TUNNEL_MODIFY_BRIDGE_IP1')
self.br_mod_ip2 = settings.getValue('TUNNEL_MODIFY_BRIDGE_IP2')
self.tunnel_type = settings.getValue('TUNNEL_TYPE')
- self._logger.debug('Creation using ' + str(self._vswitch_class))
def setup(self):
""" Sets up the switch for VxLAN overlay PTUNP (tunnel encap or decap)
"""
self._logger.debug('Setting up phy-tun-phy tunneling scenario')
- if self.tunnel_type is 'vxlan':
+ if self.tunnel_type == 'vxlan':
self._setup_vxlan_encap_decap()
else:
self._logger.error("Only VxLAN is supported for now")
@@ -78,7 +65,7 @@ class VswitchControllerPtunP(IVswitchController):
physical ports. Two more bridges br-mod1 and br-mod2 to mangle
and redirect the packets from one tunnel port to other.
"""
- self._logger.debug('Setup using ' + str(self._vswitch_class))
+ self._logger.debug('Setup using %s', str(self._vswitch_class))
try:
self._vswitch.start()
self._vswitch.add_switch(self.bridge_phy1)
@@ -156,23 +143,23 @@ class VswitchControllerPtunP(IVswitchController):
self._vswitch.del_flow(self.bridge_phy2)
self._vswitch.del_flow(self.bridge_mod1)
self._vswitch.del_flow(self.bridge_mod2)
- flow = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number,
+ flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy1_number,
phy3_number)
self._vswitch.add_flow(self.bridge_phy1, flow)
- flow = add_ports_to_flow(_FLOW_TEMPLATE, phy3_number,
+ flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy3_number,
phy1_number)
self._vswitch.add_flow(self.bridge_phy1, flow)
- flow = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number,
+ flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy2_number,
phy4_number)
self._vswitch.add_flow(self.bridge_phy2, flow)
- flow = add_ports_to_flow(_FLOW_TEMPLATE, phy4_number,
+ flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy4_number,
phy2_number)
self._vswitch.add_flow(self.bridge_phy2, flow)
- flow = add_ports_to_flow(_FLOW_TEMPLATE, phy5_number,
+ flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy5_number,
'LOCAL')
self._vswitch.add_flow(self.bridge_mod1, flow)
- mod_flow_template = _FLOW_TEMPLATE.copy()
+ mod_flow_template = settings.getValue('OVS_FLOW_TEMPLATE').copy()
mod_flow_template.update({'ip':'',
'actions':
['mod_dl_src:' + str(vxlan_rem_mac2),
@@ -183,10 +170,10 @@ class VswitchControllerPtunP(IVswitchController):
})
flow = add_ports_to_flow(mod_flow_template, 'LOCAL', phy5_number)
self._vswitch.add_flow(self.bridge_mod1, flow)
- flow = add_ports_to_flow(_FLOW_TEMPLATE, phy6_number,
+ flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy6_number,
'LOCAL')
self._vswitch.add_flow(self.bridge_mod2, flow)
- mod_flow_template = _FLOW_TEMPLATE.copy()
+ mod_flow_template = settings.getValue('OVS_FLOW_TEMPLATE').copy()
mod_flow_template.update({'ip':'',
'actions':
['mod_dl_src:' + str(vxlan_rem_mac1),
@@ -204,35 +191,24 @@ class VswitchControllerPtunP(IVswitchController):
def stop(self):
"""Tears down the switch created in setup().
"""
- self._logger.debug('Stop using ' + str(self._vswitch_class))
+ self._logger.debug('Stop using %s', str(self._vswitch_class))
self._vswitch.stop()
- def __enter__(self):
- self.setup()
-
- def __exit__(self, type_, value, traceback):
- self.stop()
-
- def get_vswitch(self):
- """See IVswitchController for description
- """
- return self._vswitch
-
def get_ports_info(self):
"""See IVswitchController for description
"""
- self._logger.debug('get_ports_info using ' + str(self._vswitch_class))
+ self._logger.debug('get_ports_info using %s', str(self._vswitch_class))
ports = self._vswitch.get_ports(self.bridge_phy1) +\
self._vswitch.get_ports(self.bridge_mod1) +\
self._vswitch.get_ports(self.bridge_phy2) +\
self._vswitch.get_ports(self.bridge_mod2)
return ports
- def dump_vswitch_flows(self):
+ def dump_vswitch_connections(self):
"""See IVswitchController for description
"""
- self._logger.debug('dump_flows using ' + str(self._vswitch_class))
- self._vswitch.dump_flows(self.bridge_phy1)
- self._vswitch.dump_flows(self.bridge_mod1)
- self._vswitch.dump_flows(self.bridge_phy2)
- self._vswitch.dump_flows(self.bridge_mod2)
+ self._logger.debug('dump_connections using %s', str(self._vswitch_class))
+ self._vswitch.dump_connections(self.bridge_phy1)
+ self._vswitch.dump_connections(self.bridge_mod1)
+ self._vswitch.dump_connections(self.bridge_phy2)
+ self._vswitch.dump_connections(self.bridge_mod2)
diff --git a/core/vswitch_controller_pxp.py b/core/vswitch_controller_pxp.py
index d4d1e764..d36ecdba 100644
--- a/core/vswitch_controller_pxp.py
+++ b/core/vswitch_controller_pxp.py
@@ -1,4 +1,4 @@
-# Copyright 2016 Intel Corporation.
+# Copyright 2016-2018 Intel Corporation., Tieto
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,34 +14,18 @@
"""VSwitch controller for multi VM scenarios with serial or parallel connection
"""
-
-import logging
import netaddr
from core.vswitch_controller import IVswitchController
-from vswitches.utils import add_ports_to_flow
from conf import settings
-_FLOW_TEMPLATE = {
- 'idle_timeout': '0'
-}
-
-_PROTO_TCP = 6
-_PROTO_UDP = 17
-
class VswitchControllerPXP(IVswitchController):
"""VSwitch controller for PXP deployment scenario.
"""
def __init__(self, deployment, vswitch_class, traffic):
- """Initializes up the prerequisites for the PXP deployment scenario.
-
- :vswitch_class: the vSwitch class to be used.
- :deployment: the deployment scenario to configure
- :traffic: dictionary with detailed traffic definition
+ """See IVswitchController for general description
"""
- self._logger = logging.getLogger(__name__)
- self._vswitch_class = vswitch_class
- self._vswitch = vswitch_class()
+ super().__init__(deployment, vswitch_class, traffic)
self._pxp_topology = 'parallel' if deployment.startswith('pvpv') else 'serial'
if deployment == 'pvp':
self._pxp_vm_count = 1
@@ -55,15 +39,13 @@ class VswitchControllerPXP(IVswitchController):
self._deployment_scenario = deployment
- self._traffic = traffic.copy()
self._bidir = True if self._traffic['bidir'] == 'True' else False
- self._logger.debug('Creation using ' + str(self._vswitch_class))
self._bridge = settings.getValue('VSWITCH_BRIDGE_NAME')
def setup(self):
""" Sets up the switch for PXP
"""
- self._logger.debug('Setup using ' + str(self._vswitch_class))
+ self._logger.debug('Setup using %s', str(self._vswitch_class))
try:
self._vswitch.start()
@@ -71,8 +53,8 @@ class VswitchControllerPXP(IVswitchController):
self._vswitch.add_switch(self._bridge)
# create physical ports
- (_, phy1_number) = self._vswitch.add_phy_port(self._bridge)
- (_, phy2_number) = self._vswitch.add_phy_port(self._bridge)
+ (phy1, _) = self._vswitch.add_phy_port(self._bridge)
+ (phy2, _) = self._vswitch.add_phy_port(self._bridge)
# create VM ports
# initialize vport array to requested number of VMs
@@ -86,54 +68,42 @@ class VswitchControllerPXP(IVswitchController):
self._logger.debug('Create %s vports for %s. VM with index %s',
nics_nr, vmindex + 1, vmindex)
for _ in range(nics_nr):
- (_, vport) = self._vswitch.add_vport(self._bridge)
+ (vport, _) = self._vswitch.add_vport(self._bridge)
vm_ports[vmindex].append(vport)
- self._vswitch.del_flow(self._bridge)
-
- # configure flows according to the TC definition
+ # configure connections according to the TC definition
if self._pxp_topology == 'serial':
- flow = _FLOW_TEMPLATE.copy()
- if self._traffic['flow_type'] == 'IP':
- flow.update({'dl_type':'0x0800',
- 'nw_src':self._traffic['l3']['srcip'],
- 'nw_dst':self._traffic['l3']['dstip']})
+ # NOTE: all traffic from VMs is sent to other ports directly
+ # without applying traffic options to avoid issues with MAC swapping
+ # and upper layer mods performed inside guests
- # insert flows for phy ports first
+ # insert connections for phy ports first
# from 1st PHY to 1st vport of 1st VM
- self._add_flow(flow,
- phy1_number,
- vm_ports[0][0],
- self._bidir)
+ self._vswitch.add_connection(self._bridge, phy1, vm_ports[0][0], self._traffic)
+ self._vswitch.add_connection(self._bridge, vm_ports[0][0], phy1)
# from last vport of last VM to 2nd phy
- self._add_flow(flow,
- vm_ports[self._pxp_vm_count-1][-1],
- phy2_number,
- self._bidir)
+ self._vswitch.add_connection(self._bridge, vm_ports[self._pxp_vm_count-1][-1], phy2)
+ self._vswitch.add_connection(self._bridge, phy2, vm_ports[self._pxp_vm_count-1][-1], self._traffic)
# add serial connections among VMs and VM NICs pairs if needed
# in case of multiple NICs pairs per VM, the pairs are chained
- # first, before flow to the next VM is created
+ # first, before connection to the next VM is created
for vmindex in range(self._pxp_vm_count):
# connect VMs NICs pairs in case of 4 and more NICs per VM
connections = [(vm_ports[vmindex][2*(x+1)-1],
vm_ports[vmindex][2*(x+1)])
for x in range(int(len(vm_ports[vmindex])/2)-1)]
for connection in connections:
- self._add_flow(flow,
- connection[0],
- connection[1],
- self._bidir)
+ self._vswitch.add_connection(self._bridge, connection[0], connection[1])
+ self._vswitch.add_connection(self._bridge, connection[1], connection[0])
# connect last NICs to the next VM if there is any
if self._pxp_vm_count > vmindex + 1:
- self._add_flow(flow,
- vm_ports[vmindex][-1],
- vm_ports[vmindex+1][0],
- self._bidir)
+ self._vswitch.add_connection(self._bridge, vm_ports[vmindex][-1], vm_ports[vmindex+1][0])
+ self._vswitch.add_connection(self._bridge, vm_ports[vmindex+1][0], vm_ports[vmindex][-1])
else:
- proto = _PROTO_TCP if self._traffic['l3']['proto'].lower() == 'tcp' else _PROTO_UDP
- dst_mac_value = netaddr.EUI(self._traffic['l2']['dstmac']).value
- dst_ip_value = netaddr.IPAddress(self._traffic['l3']['dstip']).value
+ mac_value = netaddr.EUI(self._traffic['l2']['dstmac']).value
+ ip_value = netaddr.IPAddress(self._traffic['l3']['dstip']).value
+ port_value = self._traffic['l4']['dstport']
# initialize stream index; every NIC pair of every VM uses unique stream
stream = 0
for vmindex in range(self._pxp_vm_count):
@@ -146,31 +116,33 @@ class VswitchControllerPXP(IVswitchController):
port_pairs = [(vm_ports[vmindex][0], vm_ports[vmindex][0])]
for port_pair in port_pairs:
- flow_p = _FLOW_TEMPLATE.copy()
- flow_v = _FLOW_TEMPLATE.copy()
-
- # update flow based on trafficgen settings
+ # override traffic options to ensure, that traffic is
+ # dispatched among VMs connected in parallel
+ options = {'multistream':1,
+ 'stream_type':self._traffic['stream_type'],
+ 'pre_installed_flows':'Yes'}
+ # update connection based on trafficgen settings
if self._traffic['stream_type'] == 'L2':
- tmp_mac = netaddr.EUI(dst_mac_value + stream)
+ tmp_mac = netaddr.EUI(mac_value + stream)
tmp_mac.dialect = netaddr.mac_unix_expanded
- flow_p.update({'dl_dst':tmp_mac})
+ options.update({'l2':{'dstmac':tmp_mac}})
elif self._traffic['stream_type'] == 'L3':
- tmp_ip = netaddr.IPAddress(dst_ip_value + stream)
- flow_p.update({'dl_type':'0x0800', 'nw_dst':tmp_ip})
+ tmp_ip = netaddr.IPAddress(ip_value + stream)
+ options.update({'l3':{'dstip':tmp_ip}})
elif self._traffic['stream_type'] == 'L4':
- flow_p.update({'dl_type':'0x0800', 'nw_proto':proto, 'tp_dst':stream})
+ options.update({'l3':{'proto':self._traffic['l3']['proto']}})
+ options.update({'l4':{'dstport':(port_value + stream) % 65536}})
else:
raise RuntimeError('Unknown stream_type {}'.format(self._traffic['stream_type']))
- # insert flow to dispatch traffic from physical ports
+ # insert connection to dispatch traffic from physical ports
# to VMs based on stream type; all traffic from VMs is
# sent to physical ports to avoid issues with MAC swapping
# and upper layer mods performed inside guests
- self._add_flow(flow_p, phy1_number, port_pair[0])
- self._add_flow(flow_v, port_pair[1], phy2_number)
- if self._bidir:
- self._add_flow(flow_p, phy2_number, port_pair[1])
- self._add_flow(flow_v, port_pair[0], phy1_number)
+ self._vswitch.add_connection(self._bridge, phy1, port_pair[0], options)
+ self._vswitch.add_connection(self._bridge, port_pair[1], phy2)
+ self._vswitch.add_connection(self._bridge, phy2, port_pair[1], options)
+ self._vswitch.add_connection(self._bridge, port_pair[0], phy1)
# every NIC pair needs its own unique traffic stream
stream += 1
@@ -182,40 +154,16 @@ class VswitchControllerPXP(IVswitchController):
def stop(self):
"""Tears down the switch created in setup().
"""
- self._logger.debug('Stop using ' + str(self._vswitch_class))
+ self._logger.debug('Stop using %s', str(self._vswitch_class))
self._vswitch.stop()
- def _add_flow(self, flow, port1, port2, reverse_flow=False):
- """ Helper method to insert flow into the vSwitch
- """
- self._vswitch.add_flow(self._bridge,
- add_ports_to_flow(flow,
- port1,
- port2))
- if reverse_flow:
- self._vswitch.add_flow(self._bridge,
- add_ports_to_flow(flow,
- port2,
- port1))
-
- def __enter__(self):
- self.setup()
-
- def __exit__(self, type_, value, traceback):
- self.stop()
-
- def get_vswitch(self):
- """See IVswitchController for description
- """
- return self._vswitch
-
def get_ports_info(self):
"""See IVswitchController for description
"""
- self._logger.debug('get_ports_info using ' + str(self._vswitch_class))
+ self._logger.debug('get_ports_info using %s', str(self._vswitch_class))
return self._vswitch.get_ports(self._bridge)
- def dump_vswitch_flows(self):
+ def dump_vswitch_connections(self):
"""See IVswitchController for description
"""
- self._vswitch.dump_flows(self._bridge)
+ self._vswitch.dump_connections(self._bridge)