diff options
author | Martin Klozik <martinx.klozik@intel.com> | 2015-09-25 18:00:17 +0100 |
---|---|---|
committer | Maryam Tahhan <maryam.tahhan@intel.com> | 2015-10-07 14:53:13 +0000 |
commit | 89e23da8e473387b2e6cb37a2b882d2d3c68655c (patch) | |
tree | 41bd86bc1447bf9bcbfa33cd95f175c258ede9d7 /core | |
parent | 1550b638fca662c5e68556702ff0316c3fc9562c (diff) |
Enable PVVP deployment for DPDK Vhost User and Vhost Cuse
Generic PVVP deployment support has been added. Two
new testcase scenarios for throughput and back2back
tests with PVVP deployment were added. Original
implementation of PVP has been refactored
Following files were affected:
modified: conf/01_testcases.conf
modified: conf/02_vswitch.conf
modified: conf/04_vnf.conf
modified: core/__init__.py
modified: core/component_factory.py
modified: core/loader/loader_servant.py
modified: core/vnf_controller.py
deleted: core/vnf_controller_p2p.py
deleted: core/vnf_controller_pvp.py
modified: core/vswitch_controller_p2p.py
modified: core/vswitch_controller_pvp.py
new file: core/vswitch_controller_pvvp.py
modified: docs/to-be-reorganized/NEWS.rst
modified: docs/to-be-reorganized/quickstart.rst
modified: src/dpdk/dpdk.py
modified: src/ovs/ofctl.py
modified: testcases/testcase.py
modified: tools/tasks.py
new file: vnfs/qemu/qemu.py
new file: vnfs/qemu/qemu_dpdk.py
modified: vnfs/qemu/qemu_dpdk_vhost_cuse.py
modified: vnfs/qemu/qemu_dpdk_vhost_user.py
modified: vnfs/vnf/vnf.py
modified: vswitches/ovs_dpdk_vhost.py
Change-Id: Ib6869a29337a184cb58c57fd96bba1183aba00ab
JIRA: VSPERF-68, VSPERF-69
Signed-off-by: Martin Klozik (martinx.klozik@intel.com)
Reviewed-by: Maryam Tahhan <maryam.tahhan@intel.com>
Reviewed-by: Brian Castelli <brian.castelli@spirent.com>
Diffstat (limited to 'core')
-rw-r--r-- | core/__init__.py | 1 | ||||
-rw-r--r-- | core/component_factory.py | 20 | ||||
-rw-r--r-- | core/loader/loader_servant.py | 6 | ||||
-rw-r--r-- | core/vnf_controller.py | 59 | ||||
-rw-r--r-- | core/vnf_controller_p2p.py | 64 | ||||
-rw-r--r-- | core/vnf_controller_pvp.py | 69 | ||||
-rw-r--r-- | core/vswitch_controller_p2p.py | 28 | ||||
-rw-r--r-- | core/vswitch_controller_pvp.py | 25 | ||||
-rw-r--r-- | core/vswitch_controller_pvvp.py | 114 |
9 files changed, 197 insertions, 189 deletions
diff --git a/core/__init__.py b/core/__init__.py index 0b41aaca..e39ec88e 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -16,5 +16,4 @@ """ import core.component_factory from core.traffic_controller import (ITrafficController) -from core.vnf_controller import (IVnfController) from core.vswitch_controller import (IVswitchController) diff --git a/core/component_factory.py b/core/component_factory.py index e8bb4de3..4da37fb7 100644 --- a/core/component_factory.py +++ b/core/component_factory.py @@ -18,8 +18,8 @@ from core.traffic_controller_rfc2544 import TrafficControllerRFC2544 from core.vswitch_controller_p2p import VswitchControllerP2P from core.vswitch_controller_pvp import VswitchControllerPVP -from core.vnf_controller_p2p import VnfControllerP2P -from core.vnf_controller_pvp import VnfControllerPVP +from core.vswitch_controller_pvvp import VswitchControllerPVVP +from core.vnf_controller import VnfController from tools.load_gen.stress.stress import Stress from tools.load_gen.stress_ng.stress_ng import StressNg from tools.load_gen.dummy.dummy import DummyLoadGen @@ -58,16 +58,16 @@ def create_vswitch(deployment_scenario, vswitch_class, bidir=True): :param vswitch_class: Reference to vSwitch class to be used. :return: IVSwitchController for the deployment_scenario """ - #TODO - full mapping from all deployment_scenarios to - #correct controller class deployment_scenario = deployment_scenario.lower() if deployment_scenario.find("p2p") >= 0: return VswitchControllerP2P(vswitch_class) elif deployment_scenario.find("pvp") >= 0: return VswitchControllerPVP(vswitch_class, bidir) + elif deployment_scenario.find("pvvp") >= 0: + return VswitchControllerPVVP(vswitch_class, bidir) def create_vnf(deployment_scenario, vnf_class): - """Return a new IVnfController for the deployment_scenario. + """Return a new VnfController for the deployment_scenario. The returned controller is configured with the given VNF class. @@ -75,15 +75,9 @@ def create_vnf(deployment_scenario, vnf_class): :param deployment_scenario: The deployment scenario name :param vswitch_class: Reference to vSwitch class to be used. - :return: IVnfController for the deployment_scenario + :return: VnfController for the deployment_scenario """ - #TODO - full mapping from all deployment_scenarios to - #correct controller class - deployment_scenario = deployment_scenario.lower() - if deployment_scenario.find("p2p") >= 0: - return VnfControllerP2P(None) - elif deployment_scenario.find("pvp") >= 0: - return VnfControllerPVP(vnf_class) + return VnfController(deployment_scenario, vnf_class) def create_collector(collector_class, result_dir, test_name): """Return a new Collector of the given class diff --git a/core/loader/loader_servant.py b/core/loader/loader_servant.py index 7966532c..3b729c23 100644 --- a/core/loader/loader_servant.py +++ b/core/loader/loader_servant.py @@ -138,10 +138,12 @@ class LoaderServant(object): result = {} for _, mod in LoaderServant._load_all_modules(path): - # find all system metric loggers defined in the module + # find all classes derived from given interface, but suppress + # interface itself and any abstract class starting with iface name gens = dict((k, v) for (k, v) in list(mod.__dict__.items()) if type(v) == type and - issubclass(v, interface) and k != interface.__name__) + issubclass(v, interface) and + not k.startswith(interface.__name__)) if gens: for (genname, gen) in list(gens.items()): result[genname] = gen diff --git a/core/vnf_controller.py b/core/vnf_controller.py index be1c7c4a..3d3be040 100644 --- a/core/vnf_controller.py +++ b/core/vnf_controller.py @@ -14,35 +14,66 @@ """ VNF Controller interface """ -class IVnfController(object): - """Abstract class which defines a VNF controller +import logging - Used to set-up and control a VNF provider for a particular - deployment scenario. +class VnfController(object): + """VNF controller class + + Used to set-up and control VNFs for specified scenario + + Attributes: + _vnf_class: A class object representing the VNF to be used. + _deployment_scenario: A string describing the scenario to set-up in the + constructor. + _vnfs: A list of vnfs controlled by the controller. """ + def __init__(self, deployment_scenario, vnf_class): + """Sets up the VNF infrastructure for the PVP deployment scenario. + + :param vnf_class: The VNF class to be used. + """ + self._logger = logging.getLogger(__name__) + self._vnf_class = vnf_class + self._deployment_scenario = deployment_scenario.upper() + if self._deployment_scenario == 'P2P': + self._vnfs = [] + if self._deployment_scenario == 'PVP': + self._vnfs = [vnf_class()] + elif self._deployment_scenario == 'PVVP': + self._vnfs = [vnf_class(), vnf_class()] + self._logger.debug('__init__ ' + str(len(self._vnfs)) + + ' VNF[s] with ' + ' '.join(map(str, self._vnfs))) + def get_vnfs(self): """Returns a list of vnfs controlled by this controller. """ - raise NotImplementedError( - "The VnfController does not implement", - "the \"get_vnfs\" function.") + self._logger.debug('get_vnfs ' + str(len(self._vnfs)) + + ' VNF[s] with ' + ' '.join(map(str, self._vnfs))) + return self._vnfs - #TODO: Decide on contextmanager or __enter/exit__ strategy <MH 2015-05-01> def start(self): """Boots all VNFs set-up by __init__. This is a blocking function. """ - raise NotImplementedError( - "The VnfController does not implement", - "the \"start\" function.") + self._logger.debug('start ' + str(len(self._vnfs)) + + ' VNF[s] with ' + ' '.join(map(str, self._vnfs))) + for vnf in self._vnfs: + vnf.start() def stop(self): """Stops all VNFs set-up by __init__. This is a blocking function. """ - raise NotImplementedError( - "The VnfController does not implement", - "the \"stop\" function.") + self._logger.debug('stop ' + str(len(self._vnfs)) + + ' VNF[s] with ' + ' '.join(map(str, self._vnfs))) + for vnf in self._vnfs: + vnf.stop() + + def __enter__(self): + self.start() + + def __exit__(self, type_, value, traceback): + self.stop() diff --git a/core/vnf_controller_p2p.py b/core/vnf_controller_p2p.py deleted file mode 100644 index a881d345..00000000 --- a/core/vnf_controller_p2p.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2015 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. -"""VNF Controller for the P2P scenario -""" - -import logging - -from core.vnf_controller import IVnfController - -class VnfControllerP2P(IVnfController): - """VNF controller for the P2P scenario. - - Does nothing as there is no VNF in P2P - - Attributes: - _vnf_class: A class object representing the VNF to be used. - _deployment_scenario: A string describing the scenario to set-up in the - constructor. - _vnfs: A list of vnfs controlled by the controller. - """ - - #TODO: Decide on contextmanager or __enter/exit__ strategy <MH 2015-05-01> - def __init__(self, vnf_class): - """Sets up the VNF infrastructure for the P2P deployment scenario. - - :param vnf_class: The VNF class to be used, this is mostly ignored. - """ - self._logger = logging.getLogger(__name__) - self._vnf_class = vnf_class - self._deployment_scenario = "P2P" - self._logger.debug('__init__ with ' + str(self._vnf_class)) - - def get_vnfs(self): - """Returns an empty list of vnfs. - """ - self._logger.debug('get_vnfs with ' + str(self._vnf_class)) - return [] - - def start(self): - """Starts nothing. - """ - self._logger.debug('start with ' + str(self._vnf_class)) - - def stop(self): - """Stops nothing. - """ - self._logger.debug('stop with ' + str(self._vnf_class)) - - def __enter__(self): - self.start() - - def __exit__(self, type_, value, traceback): - self.stop() diff --git a/core/vnf_controller_pvp.py b/core/vnf_controller_pvp.py deleted file mode 100644 index 1878db10..00000000 --- a/core/vnf_controller_pvp.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright 2015 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. -"""VNF Controller for the PVP scenario -""" - -import logging - -from core.vnf_controller import IVnfController - -class VnfControllerPVP(IVnfController): - """VNF controller for the PVP scenario. - - Used to set-up and control a VNF provider for the PVP scenario. - - Attributes: - _vnf_class: A class object representing the VNF to be used. - _deployment_scenario: A string describing the scenario to set-up in the - constructor. - _vnfs: A list of vnfs controlled by the controller. - """ - - #TODO: Decide on contextmanager or __enter/exit__ strategy <MH 2015-05-01> - def __init__(self, vnf_class): - """Sets up the VNF infrastructure for the PVP deployment scenario. - - :param vnf_class: The VNF class to be used. - """ - self._logger = logging.getLogger(__name__) - self._vnf_class = vnf_class() - self._deployment_scenario = "PVP" - self._vnfs = [vnf_class(deployment=self._deployment_scenario)] - self._logger.debug('__init__ with ' + str(self._vnfs[0])) - #TODO call vnf.xxx to carry out the required setup - - def get_vnfs(self): - """See IVnfController for description - """ - self._logger.debug('get_vnfs with ' + str(self._vnfs[0])) - return self._vnfs - - def start(self): - """See IVnfController for description - """ - self._logger.debug('start with ' + str(self._vnfs[0])) - for vnf in self._vnfs: - vnf.start() - - def stop(self): - """See IVnfController for description - """ - self._logger.debug('stop with ' + str(self._vnfs[0])) - self._vnfs[0].stop() - - def __enter__(self): - self.start() - - def __exit__(self, type_, value, traceback): - self.stop() diff --git a/core/vswitch_controller_p2p.py b/core/vswitch_controller_p2p.py index a1158d4e..c15f7ef8 100644 --- a/core/vswitch_controller_p2p.py +++ b/core/vswitch_controller_p2p.py @@ -18,12 +18,11 @@ import logging from core.vswitch_controller import IVswitchController -from vswitches.utils import add_ports_to_flow +from conf import settings _FLOW_TEMPLATE = { 'idle_timeout': '0' } -BRIDGE_NAME = 'br0' class VswitchControllerP2P(IVswitchController): """VSwitch controller for P2P deployment scenario. @@ -53,41 +52,42 @@ class VswitchControllerP2P(IVswitchController): try: self._vswitch.start() - self._vswitch.add_switch(BRIDGE_NAME) + bridge = settings.getValue('VSWITCH_BRIDGE_NAME') + self._vswitch.add_switch(bridge) - (_, phy1_number) = self._vswitch.add_phy_port(BRIDGE_NAME) - (_, phy2_number) = self._vswitch.add_phy_port(BRIDGE_NAME) + (_, _) = self._vswitch.add_phy_port(bridge) + (_, _) = self._vswitch.add_phy_port(bridge) - self._vswitch.del_flow(BRIDGE_NAME) + 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_NAME, flow) + 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 flow = {'table':'1', 'priority':'1', 'in_port':'1', 'actions': ['write_actions(output:2)', 'write_metadata:2', - 'goto_table:2']} - self._vswitch.add_flow(BRIDGE_NAME, flow) + 'goto_table:2']} + self._vswitch.add_flow(bridge, flow) flow = {'table':'1', 'priority':'1', 'in_port':'2', 'actions': ['write_actions(output:1)', 'write_metadata:1', - 'goto_table:2']} - self._vswitch.add_flow(BRIDGE_NAME, flow) + 'goto_table:2']} + self._vswitch.add_flow(bridge, flow) # 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_NAME, flow) + 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_NAME, flow) + self._vswitch.add_flow(bridge, flow) except: self._vswitch.stop() raise @@ -113,4 +113,4 @@ class VswitchControllerP2P(IVswitchController): """See IVswitchController for description """ self._logger.debug('get_ports_info using ' + str(self._vswitch_class)) - return self._vswitch.get_ports(BRIDGE_NAME) + return self._vswitch.get_ports(settings.getValue('VSWITCH_BRIDGE_NAME')) diff --git a/core/vswitch_controller_pvp.py b/core/vswitch_controller_pvp.py index 8c409dc2..80c0fdb2 100644 --- a/core/vswitch_controller_pvp.py +++ b/core/vswitch_controller_pvp.py @@ -19,11 +19,11 @@ import logging from core.vswitch_controller import IVswitchController from vswitches.utils import add_ports_to_flow +from conf import settings _FLOW_TEMPLATE = { 'idle_timeout': '0' } -BRIDGE_NAME = 'br0' class VswitchControllerPVP(IVswitchController): """VSwitch controller for PVP deployment scenario. @@ -54,28 +54,29 @@ class VswitchControllerPVP(IVswitchController): try: self._vswitch.start() - self._vswitch.add_switch(BRIDGE_NAME) + bridge = settings.getValue('VSWITCH_BRIDGE_NAME') + self._vswitch.add_switch(bridge) - (_, phy1_number) = self._vswitch.add_phy_port(BRIDGE_NAME) - (_, phy2_number) = self._vswitch.add_phy_port(BRIDGE_NAME) - (_, vport1_number) = self._vswitch.add_vport(BRIDGE_NAME) - (_, vport2_number) = self._vswitch.add_vport(BRIDGE_NAME) + (_, phy1_number) = self._vswitch.add_phy_port(bridge) + (_, phy2_number) = self._vswitch.add_phy_port(bridge) + (_, vport1_number) = self._vswitch.add_vport(bridge) + (_, vport2_number) = self._vswitch.add_vport(bridge) - self._vswitch.del_flow(BRIDGE_NAME) + self._vswitch.del_flow(bridge) flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number, vport1_number) flow2 = add_ports_to_flow(_FLOW_TEMPLATE, vport2_number, phy2_number) - self._vswitch.add_flow(BRIDGE_NAME, flow1) - self._vswitch.add_flow(BRIDGE_NAME, flow2) + self._vswitch.add_flow(bridge, flow1) + self._vswitch.add_flow(bridge, flow2) if self._bidir: flow3 = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number, vport2_number) flow4 = add_ports_to_flow(_FLOW_TEMPLATE, vport1_number, phy1_number) - self._vswitch.add_flow(BRIDGE_NAME, flow3) - self._vswitch.add_flow(BRIDGE_NAME, flow4) + self._vswitch.add_flow(bridge, flow3) + self._vswitch.add_flow(bridge, flow4) except: self._vswitch.stop() @@ -102,4 +103,4 @@ class VswitchControllerPVP(IVswitchController): """See IVswitchController for description """ self._logger.debug('get_ports_info using ' + str(self._vswitch_class)) - return self._vswitch.get_ports(BRIDGE_NAME) + return self._vswitch.get_ports(settings.getValue('VSWITCH_BRIDGE_NAME')) diff --git a/core/vswitch_controller_pvvp.py b/core/vswitch_controller_pvvp.py new file mode 100644 index 00000000..b445f9bd --- /dev/null +++ b/core/vswitch_controller_pvvp.py @@ -0,0 +1,114 @@ +# Copyright 2015 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. + +"""VSwitch controller for Physical to VM to Physical deployment +""" + +import logging + +from core.vswitch_controller import IVswitchController +from vswitches.utils import add_ports_to_flow +from conf import settings + +_FLOW_TEMPLATE = { + 'idle_timeout': '0' +} + +class VswitchControllerPVVP(IVswitchController): + """VSwitch controller for PVVP 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, bidir=False): + """Initializes up the prerequisites for the PVVP 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 = "PVVP" + self._bidir = bidir + self._logger.debug('Creation using ' + str(self._vswitch_class)) + + def setup(self): + """ Sets up the switch for PVVP + """ + self._logger.debug('Setup using ' + str(self._vswitch_class)) + + try: + self._vswitch.start() + + bridge = settings.getValue('VSWITCH_BRIDGE_NAME') + self._vswitch.add_switch(bridge) + + (_, phy1_number) = self._vswitch.add_phy_port(bridge) + (_, phy2_number) = self._vswitch.add_phy_port(bridge) + (_, vport1_number) = self._vswitch.add_vport(bridge) + (_, vport2_number) = self._vswitch.add_vport(bridge) + (_, vport3_number) = self._vswitch.add_vport(bridge) + (_, vport4_number) = self._vswitch.add_vport(bridge) + + self._vswitch.del_flow(bridge) + flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number, + vport1_number) + flow2 = add_ports_to_flow(_FLOW_TEMPLATE, vport2_number, + vport3_number) + flow3 = add_ports_to_flow(_FLOW_TEMPLATE, vport4_number, + phy2_number) + self._vswitch.add_flow(bridge, flow1) + self._vswitch.add_flow(bridge, flow2) + self._vswitch.add_flow(bridge, flow3) + + if self._bidir: + flow4 = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number, + vport4_number) + flow5 = add_ports_to_flow(_FLOW_TEMPLATE, vport3_number, + vport2_number) + flow6 = add_ports_to_flow(_FLOW_TEMPLATE, vport1_number, + phy1_number) + self._vswitch.add_flow(bridge, flow4) + self._vswitch.add_flow(bridge, flow5) + self._vswitch.add_flow(bridge, flow6) + + except: + self._vswitch.stop() + raise + + def stop(self): + """Tears down the switch created in setup(). + """ + self._logger.debug('Stop using ' + 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')) |