aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/__init__.py20
-rw-r--r--core/collector_controller.py55
-rw-r--r--core/component_factory.py101
-rw-r--r--core/loader/__init__.py20
-rwxr-xr-xcore/loader/loader.py153
-rw-r--r--core/loader/loader_servant.py180
-rw-r--r--core/results/__init__.py17
-rw-r--r--core/results/results.py36
-rw-r--r--core/results/results_constants.py77
-rw-r--r--core/traffic_controller.py60
-rw-r--r--core/traffic_controller_rfc2544.py135
-rw-r--r--core/vnf_controller.py48
-rw-r--r--core/vnf_controller_p2p.py58
-rw-r--r--core/vnf_controller_pvp.py60
-rw-r--r--core/vswitch_controller.py50
-rw-r--r--core/vswitch_controller_p2p.py90
-rw-r--r--core/vswitch_controller_pvp.py69
17 files changed, 1229 insertions, 0 deletions
diff --git a/core/__init__.py b/core/__init__.py
new file mode 100644
index 00000000..0b41aaca
--- /dev/null
+++ b/core/__init__.py
@@ -0,0 +1,20 @@
+# 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.
+
+"""Core structural interfaces and their implementations
+"""
+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/collector_controller.py b/core/collector_controller.py
new file mode 100644
index 00000000..10c9bce7
--- /dev/null
+++ b/core/collector_controller.py
@@ -0,0 +1,55 @@
+# 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.
+
+"""CollectorController class
+"""
+from core.results.results import IResults
+
+class CollectorController(IResults):
+ """Class which defines a collector controller object.
+
+ Used to set-up and control a collector provider.
+ """
+
+ def __init__(self, collector_class):
+ """Sets up the prerequisites for the Collector.
+
+ :param collector_class: the Collector class to be used.
+ """
+ self._collector = collector_class()
+ self._results = []
+
+ def log_mem_stats(self):
+ """Log memory stats.
+ """
+ self._results.append(self._collector.log_mem_stats())
+
+ def log_cpu_stats(self):
+ """Log CPU stats.
+ """
+ self._results.append(self._collector.log_cpu_stats())
+
+ def get_results(self):
+ """Return collected CPU and memory stats.
+
+ Implements IResults i/f, see IResults for details.
+ """
+ return self._results
+
+ def print_results(self):
+ """Prints collected CPU and memory stats.
+
+ Implements IResults i/f, see IResults for details.
+ """
+ print(self._results)
diff --git a/core/component_factory.py b/core/component_factory.py
new file mode 100644
index 00000000..eb963d6f
--- /dev/null
+++ b/core/component_factory.py
@@ -0,0 +1,101 @@
+# 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.
+
+"""Functions for creating controller objects based on deployment or traffic
+"""
+
+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.collector_controller import CollectorController
+
+
+def __init__():
+ """Finds and loads all the modules required.
+
+ Very similar code to load_trafficgens().
+ """
+ pass
+
+def create_traffic(traffic_type, trafficgen_class):
+ """Return a new IVSwitchController for the traffic type.
+
+ The returned traffic controller has the given traffic type and traffic
+ generator class.
+
+ traffic_types: 'rfc2544_throughput'
+
+ :param traffic_type: Name of traffic type
+ :param trafficgen_class: Reference to traffic generator class to be used.
+ :return: A new ITrafficController
+ """
+ #TODO - full mapping from all traffic_types to
+ #correct controller class
+ return TrafficControllerRFC2544(trafficgen_class)
+
+def create_vswitch(deployment_scenario, vswitch_class):
+ """Return a new IVSwitchController for the deployment_scenario.
+
+ The returned controller is configured with the given vSwitch class.
+
+ Deployment scenarios: 'p2p', 'pvp'
+
+ :param deployment_scenario: The deployment scenario name
+ :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)
+
+def create_vnf(deployment_scenario, vnf_class):
+ """Return a new IVnfController for the deployment_scenario.
+
+ The returned controller is configured with the given VNF class.
+
+ Deployment scenarios: 'p2p', 'pvp'
+
+ :param deployment_scenario: The deployment scenario name
+ :param vswitch_class: Reference to vSwitch class to be used.
+ :return: IVnfController 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(vnf_class)
+ elif deployment_scenario.find("pvp") >= 0:
+ return VnfControllerPVP(vnf_class)
+
+def create_collector(collector, collector_class):
+ """Return a new CollectorController of the given class
+
+ Supported collector type strings:
+ 'cpu'
+ 'memory':
+
+ :param collector: Collector type string
+ :param collector_class: The collector class to be used.
+ :return: A new CollectorController.
+ """
+ collector = collector.lower()
+ if "cpu" in collector or "memory" in collector:
+ return CollectorController(collector_class)
+
diff --git a/core/loader/__init__.py b/core/loader/__init__.py
new file mode 100644
index 00000000..023f30a6
--- /dev/null
+++ b/core/loader/__init__.py
@@ -0,0 +1,20 @@
+# 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.
+
+"""Loader package
+
+This packet is responsible for loading classes & creating instances
+of requested objects. This component directly depends upon conf.
+"""
+from .loader import Loader
diff --git a/core/loader/loader.py b/core/loader/loader.py
new file mode 100755
index 00000000..57787751
--- /dev/null
+++ b/core/loader/loader.py
@@ -0,0 +1,153 @@
+# 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.
+
+"""Loader module definition.
+"""
+
+from conf import settings
+from core.loader.loader_servant import LoaderServant
+from tools.pkt_gen.trafficgen import ITrafficGenerator
+from tools.collectors.collector import ICollector
+from vswitches.vswitch import IVSwitch
+
+class Loader(object):
+ """Loader class - main object context holder.
+ """
+ _trafficgen_loader = None
+ _metrics_loader = None
+ _vswitch_loader = None
+
+ def __init__(self):
+ """Loader ctor - initialization method.
+
+ All data is read from configuration each time Loader instance is
+ created. It is up to creator to maintain object life cycle if this
+ behavior is unwanted.
+ """
+ self._trafficgen_loader = LoaderServant(
+ settings.getValue('TRAFFICGEN_DIR'),
+ settings.getValue('TRAFFICGEN'),
+ ITrafficGenerator)
+
+ self._metrics_loader = LoaderServant(
+ settings.getValue('COLLECTOR_DIR'),
+ settings.getValue('COLLECTOR'),
+ ICollector)
+
+ self._vswitch_loader = LoaderServant(
+ settings.getValue('VSWITCH_DIR'),
+ settings.getValue('VSWITCH'),
+ IVSwitch)
+
+ def get_trafficgen(self):
+ """Returns a new instance configured traffic generator.
+
+ :return: ITrafficGenerator implementation if available, None otherwise.
+ """
+ return self._trafficgen_loader.get_class()()
+
+ def get_trafficgen_class(self):
+ """Returns type of currently configured traffic generator.
+
+ :return: Type of ITrafficGenerator implementation if available.
+ None otherwise.
+ """
+ return self._trafficgen_loader.get_class()
+
+ def get_trafficgens(self):
+ """Returns dictionary of all available traffic generators.
+
+ :return: Dictionary of traffic generators.
+ - key: name of the class which implements ITrafficGenerator,
+ - value: Type of traffic generator which implements
+ ITrafficGenerator.
+ """
+ return self._trafficgen_loader.get_classes()
+
+ def get_trafficgens_printable(self):
+ """Returns all available traffic generators in printable format.
+
+ :return: String containing printable list of traffic generators.
+ """
+ return self._trafficgen_loader.get_classes_printable()
+
+ def get_collector(self):
+ """Returns instance of currently configured collector implementation.
+
+ :return: ICollector implementation if available, None otherwise.
+ """
+ return self._metrics_loader.get_class()()
+
+ def get_collector_class(self):
+ """Returns type of currently configured collector implementation.
+
+ :return: Type of ICollector implementation if available.
+ None otherwise.
+ """
+ return self._metrics_loader.get_class()
+
+ def get_collectors(self):
+ """Returns dictionary of all available collectors.
+
+ :return: Dictionary of collectors.
+ - key: name of the class which implements ICollector,
+ - value: Type of traffic generator which implements ICollector.
+ """
+ return self._metrics_loader.get_classes()
+
+ def get_collectors_printable(self):
+ """Returns all available collectors in printable format.
+
+ :return: String containing printable list of collectors.
+ """
+ return self._metrics_loader.get_classes_printable()
+
+ def get_vswitch(self):
+ """Returns instance of currently configured vswitch implementation.
+
+ :return: IVSwitch implementation if available, None otherwise.
+ """
+ return self._vswitch_loader.get_class()()
+
+ def get_vswitch_class(self):
+ """Returns type of currently configured vswitch implementation.
+
+ :return: Type of IVSwitch implementation if available.
+ None otherwise.
+ """
+ return self._vswitch_loader.get_class()
+
+ def get_vswitches(self):
+ """Returns dictionary of all available vswitches.
+
+ :return: Dictionary of vswitches.
+ - key: name of the class which implements IVSwitch,
+ - value: Type of traffic generator which implements IVSwitch.
+ """
+ return self._vswitch_loader.get_classes()
+
+ def get_vswitches_printable(self):
+ """Returns all available vswitches in printable format.
+
+ :return: String containing printable list of vswitches.
+ """
+ return self._vswitch_loader.get_classes_printable()
+
+ def get_vnf_class(self):
+ """Returns a new instance of the configured VNF
+
+ Currently always returns None
+ """
+ #TODO: Load the VNF class
+ return None
diff --git a/core/loader/loader_servant.py b/core/loader/loader_servant.py
new file mode 100644
index 00000000..7966532c
--- /dev/null
+++ b/core/loader/loader_servant.py
@@ -0,0 +1,180 @@
+# 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.
+
+"""Loader servant module used by Loader.
+
+Module is inteded to be private to serve only Loader itself, nevertheless
+some methods are exposed outside and can be used by any other clients:
+- load_modules(self, path, interface)
+- load_module(self, path, interface, class_name)
+Those method are stateless static members.
+
+"""
+import os
+from os import sys
+import imp
+import fnmatch
+import logging
+
+
+class LoaderServant(object):
+ """Class implements basic dynamic import operations.
+ """
+ _class_name = None
+ _path = None
+ _interface = None
+
+ def __init__(self, path, class_name, interface):
+ """LoaderServant constructor
+
+ Intializes all data needed for import operations.
+
+ Attributes:
+ path: path to directory which contains implementations derived from
+ interface.
+ class_name: Class name which will be returned in get_class
+ method, if such definition exists in directory
+ represented by path,
+ interface: interface type. Every object which doesn't
+ implement this particular interface will be
+ filtered out.
+ """
+ self._class_name = class_name
+ self._path = path
+ self._interface = interface
+
+ def get_class(self):
+ """Returns class type based on parameters passed in __init__.
+
+ :return: Type of the found class.
+ None if class hasn't been found
+ """
+
+ return self.load_module(path=self._path,
+ interface=self._interface,
+ class_name=self._class_name)
+
+ def get_classes(self):
+ """Returns all classes in path derived from interface
+
+ :return: Dictionary with following data:
+ - key: String representing class name,
+ - value: Class type.
+ """
+ return self.load_modules(path=self._path,
+ interface=self._interface)
+
+ def get_classes_printable(self):
+ """Returns all classes derived from _interface found in path
+
+ :return: String - list of classes in printable format.
+ """
+
+ out = self.load_modules(path=self._path,
+ interface=self._interface)
+ results = []
+
+ for (name, mod) in list(out.items()):
+ desc = (mod.__doc__ or 'No description').strip().split('\n')[0]
+ results.append((name, desc))
+
+ output = [
+ 'Classes derived from: ' + self._interface.__name__ + '\n======\n']
+
+ for (name, desc) in results:
+ output.append('* %-18s%s' % ('%s:' % name, desc))
+
+ output.append('')
+
+ output.append('')
+
+ return '\n'.join(output)
+
+ @staticmethod
+ def load_module(path, interface, class_name):
+ """Imports everything from given path and returns class type
+
+ This is based on following conditions:
+ - Class is derived from interface,
+ - Class type name matches class_name.
+
+ :return: Type of the found class.
+ None if class hasn't been found
+ """
+
+ results = LoaderServant.load_modules(
+ path=path, interface=interface)
+
+ if class_name in results:
+ logging.info(
+ "Class found: " + class_name + ".")
+ return results.get(class_name)
+
+ return None
+
+ @staticmethod
+ def load_modules(path, interface):
+ """Returns dictionary of class name/class type found in path
+
+ This is based on following conditions:
+ - classes found under path are derived from interface.
+ - class is not interface itself.
+
+ :return: Dictionary with following data:
+ - key: String representing class name,
+ - value: Class type.
+ """
+ result = {}
+
+ for _, mod in LoaderServant._load_all_modules(path):
+ # find all system metric loggers defined in the module
+ gens = dict((k, v) for (k, v) in list(mod.__dict__.items())
+ if type(v) == type and
+ issubclass(v, interface) and k != interface.__name__)
+ if gens:
+ for (genname, gen) in list(gens.items()):
+ result[genname] = gen
+ return result
+
+ @staticmethod
+ def _load_all_modules(path):
+ """Load all modules from ``path`` directory.
+
+ This is based on the design used by OFTest:
+ https://github.com/floodlight/oftest/blob/master/oft
+
+ :param path: Path to a folder of modules.
+
+ :return: List of modules in a folder.
+ """
+ mods = []
+
+ for root, _, filenames in os.walk(path):
+ # Iterate over each python file
+ for filename in fnmatch.filter(filenames, '[!.]*.py'):
+ modname = os.path.splitext(os.path.basename(filename))[0]
+
+ try:
+ if modname in sys.modules:
+ mod = sys.modules[modname]
+ else:
+ mod = imp.load_module(
+ modname, *imp.find_module(modname, [root]))
+ except ImportError:
+ logging.error('Could not import file ' + filename)
+ raise
+
+ mods.append((modname, mod))
+
+ return mods
diff --git a/core/results/__init__.py b/core/results/__init__.py
new file mode 100644
index 00000000..38521211
--- /dev/null
+++ b/core/results/__init__.py
@@ -0,0 +1,17 @@
+# 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.
+"""Results package contains the core IResults interface
+"""
+
+from core.results import results
diff --git a/core/results/results.py b/core/results/results.py
new file mode 100644
index 00000000..f73f6af5
--- /dev/null
+++ b/core/results/results.py
@@ -0,0 +1,36 @@
+# 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.
+"""IResult interface definition.
+"""
+
+class IResults(object):
+ """Abstract class defining an interface for gathering results
+ """
+ def print_results(self):
+ """Prints gathered results to screen.
+ """
+ raise NotImplementedError("This class does not implement the" \
+ " \"print_results\" function.")
+
+ def get_results(self):
+ """Returns gathered results as a list of dictionaries.
+
+ Each list element represents one record of data.
+
+ :return: Results dictionary
+ - key: Column name
+ - value: Column value.
+ """
+ raise NotImplementedError("This class does not implement the" \
+ " \"get_results\" function.")
diff --git a/core/results/results_constants.py b/core/results/results_constants.py
new file mode 100644
index 00000000..2af3f8d8
--- /dev/null
+++ b/core/results/results_constants.py
@@ -0,0 +1,77 @@
+# 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.
+"""ResultsConstants class
+"""
+
+class ResultsConstants(object):
+ """Constant fields holder used by various IResult implementations.
+ """
+ TYPE = 'type'
+ ID = 'id'
+ PACKET_SIZE = 'packet_size'
+ DEPLOYMENT = 'deployment'
+
+ UNKNOWN_VALUE = "Unknown"
+
+ #Traffic Constants
+ #RFC2544 Throughput & Continuous
+ THROUGHPUT_TX_FPS = 'throughput_tx_fps'
+ THROUGHPUT_RX_FPS = 'throughput_rx_fps'
+ THROUGHPUT_TX_MBPS = 'throughput_tx_mbps'
+ THROUGHPUT_RX_MBPS = 'throughput_rx_mbps'
+ THROUGHPUT_TX_PERCENT = 'throughput_tx_percent'
+ THROUGHPUT_RX_PERCENT = 'throughput_rx_percent'
+ MIN_LATENCY_NS = 'min_latency_ns'
+ MAX_LATENCY_NS = 'max_latency_ns'
+ AVG_LATENCY_NS = 'avg_latency_ns'
+ #Burst traffic
+ TX_FRAMES = 'tx_frames'
+ RX_FRAMES = 'rx_frames'
+ TX_BYTES = 'tx_bytes'
+ RX_BYTES = 'rx_bytes'
+ PAYLOAD_ERR = 'payload_err'
+ SEQ_ERR = 'seq_err'
+ #Back2Back
+ B2B_RX_FPS = 'b2b_rx_fps'
+ B2B_TX_FPS = 'b2b_tx_fps'
+ B2B_RX_PERCENT = 'b2b_rx_percent'
+ B2B_TX_PERCENT = 'b2b_tx_percent'
+ B2B_TX_COUNT = 'b2b_tx_count'
+ B2B_FRAMES = 'b2b_frames'
+ B2B_FRAME_LOSS_FRAMES = 'b2b_frame_loss_frames'
+ B2B_FRAME_LOSS_PERCENT = 'b2b_frame_loss_percent'
+
+ @staticmethod
+ def get_traffic_constants():
+ """Method returns all Constants used to store results.
+
+ These data can be used to generate final output.
+
+ :return: List of Strings which contains column names used as a result
+ This applies to any traffic(RFC2544 throughput or continuous flow)
+ operation.
+ """
+ return [ResultsConstants.TYPE,
+ ResultsConstants.ID,
+ ResultsConstants.PACKET_SIZE,
+ ResultsConstants.DEPLOYMENT,
+ ResultsConstants.THROUGHPUT_TX_FPS,
+ ResultsConstants.THROUGHPUT_RX_FPS,
+ ResultsConstants.THROUGHPUT_TX_MBPS,
+ ResultsConstants.THROUGHPUT_RX_MBPS,
+ ResultsConstants.THROUGHPUT_TX_PERCENT,
+ ResultsConstants.THROUGHPUT_RX_PERCENT,
+ ResultsConstants.MIN_LATENCY_NS,
+ ResultsConstants.MAX_LATENCY_NS,
+ ResultsConstants.AVG_LATENCY_NS]
diff --git a/core/traffic_controller.py b/core/traffic_controller.py
new file mode 100644
index 00000000..428e91f8
--- /dev/null
+++ b/core/traffic_controller.py
@@ -0,0 +1,60 @@
+# 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.
+
+"""Interface to traffic controllers
+"""
+
+class ITrafficController(object):
+ """Abstract class which defines a traffic controller object
+
+ Used to setup and control a traffic generator for a particular deployment
+ scenario.
+ """
+
+ def send_traffic(self, traffic):
+ """Triggers traffic to be sent from the traffic generator.
+
+ This is a blocking function.
+
+ :param traffic: A dictionary describing the traffic to send.
+ """
+ raise NotImplementedError(
+ "The TrafficController does not implement",
+ "the \"send_traffic\" function.")
+
+ def send_traffic_async(self, traffic, function):
+ """Triggers traffic to be sent asynchronously.
+
+ This is not a blocking function.
+
+ :param traffic: A dictionary describing the traffic to send.
+ :param function: A dictionary describing the function to call between
+ send and wait in the form:
+ function = {
+ 'function' : package.module.function,
+ 'args' : args
+ }
+ If this function requires more than one argument, all should be
+ should be passed using the args list and appropriately handled.
+ """
+ raise NotImplementedError(
+ "The TrafficController does not implement",
+ "the \"send_traffic_async\" function.")
+
+ def stop_traffic(self):
+ """Kills traffic being sent from the traffic generator.
+ """
+ raise NotImplementedError(
+ "The TrafficController does not implement",
+ "the \"stop_traffic\" function.")
diff --git a/core/traffic_controller_rfc2544.py b/core/traffic_controller_rfc2544.py
new file mode 100644
index 00000000..003307bf
--- /dev/null
+++ b/core/traffic_controller_rfc2544.py
@@ -0,0 +1,135 @@
+# 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.
+"""RFC2544 Traffic Controller implementation.
+"""
+import logging
+
+from core.traffic_controller import ITrafficController
+from core.results.results_constants import ResultsConstants
+from core.results.results import IResults
+from conf import settings
+from conf import get_test_param
+
+
+class TrafficControllerRFC2544(ITrafficController, IResults):
+ """Traffic controller for RFC2544 traffic
+
+ Used to setup and control a traffic generator for an RFC2544 deployment
+ traffic scenario.
+ """
+
+ def __init__(self, traffic_gen_class):
+ """Initialise the trafficgen and store.
+
+ :param traffic_gen_class: The traffic generator class to be used.
+ """
+ self._logger = logging.getLogger(__name__)
+ self._logger.debug("__init__")
+ self._traffic_gen_class = traffic_gen_class()
+ self._traffic_started = False
+ self._traffic_started_call_count = 0
+ self._packet_sizes = settings.getValue('TRAFFICGEN_PKT_SIZES')
+ self._trials = get_test_param('rfc2544_trials', 1)
+ self._results = []
+
+ def __enter__(self):
+ """Call initialisation function.
+ """
+ self._traffic_gen_class.connect()
+
+ def __exit__(self, type_, value, traceback):
+ """Stop traffic, clean up.
+ """
+ if self._traffic_started:
+ self.stop_traffic()
+
+ @staticmethod
+ def _append_results(result_dict, packet_size):
+ """Adds common values to traffic generator results.
+
+ :param result_dict: Dictionary containing results from trafficgen
+ :param packet_size: Packet size value.
+
+ :returns: dictionary of results with addictional entries.
+ """
+
+ ret_value = result_dict
+
+ #TODO Old TOIT controller had knowledge about scenario beeing
+ #executed, should new controller also fill Configuration & ID,
+ # or this should be passed to TestCase?
+ ret_value[ResultsConstants.TYPE] = 'rfc2544'
+ ret_value[ResultsConstants.PACKET_SIZE] = str(packet_size)
+
+ return ret_value
+
+ def send_traffic(self, traffic):
+ """See ITrafficController for description
+ """
+ self._logger.debug('send_traffic with ' +
+ str(self._traffic_gen_class))
+
+ for packet_size in self._packet_sizes:
+ traffic['l2'] = {'framesize': packet_size}
+ result = self._traffic_gen_class.send_rfc2544_throughput(
+ traffic,
+ trials=int(self._trials),
+ duration=int(get_test_param('rfc2544_duration', 20)))
+ result = TrafficControllerRFC2544._append_results(result,
+ packet_size)
+ self._results.append(result)
+
+ def send_traffic_async(self, traffic, function):
+ """See ITrafficController for description
+ """
+ self._logger.debug('send_traffic_async with ' +
+ str(self._traffic_gen_class))
+
+ for packet_size in self._packet_sizes:
+ traffic['l2'] = {'framesize': packet_size}
+ self._traffic_gen_class.start_rfc2544_throughput(
+ traffic,
+ trials=int(self._trials),
+ duration=int(get_test_param('rfc2544_duration', 20)))
+ self._traffic_started = True
+ if len(function['args']) > 0:
+ function['function'](function['args'])
+ else:
+ function['function']()
+ result = self._traffic_gen_class.wait_rfc2544_throughput()
+ result = TrafficControllerRFC2544._append_results(result,
+ packet_size)
+ self._results.append(result)
+
+ def stop_traffic(self):
+ """Kills traffic being sent from the traffic generator.
+ """
+ self._logger.debug("stop_traffic()")
+
+ def print_results(self):
+ """IResult interface implementation.
+ """
+ counter = 0
+ for item in self._results:
+ logging.info("Record: " + str(counter))
+ counter += 1
+ for(key, value) in list(item.items()):
+ logging.info(" Key: " + str(key) +
+ ", Value: " + str(value))
+
+
+ def get_results(self):
+ """IResult interface implementation.
+ """
+ return self._results
diff --git a/core/vnf_controller.py b/core/vnf_controller.py
new file mode 100644
index 00000000..be1c7c4a
--- /dev/null
+++ b/core/vnf_controller.py
@@ -0,0 +1,48 @@
+# 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 interface
+"""
+
+class IVnfController(object):
+ """Abstract class which defines a VNF controller
+
+ Used to set-up and control a VNF provider for a particular
+ deployment scenario.
+ """
+
+ def get_vnfs(self):
+ """Returns a list of vnfs controlled by this controller.
+ """
+ raise NotImplementedError(
+ "The VnfController does not implement",
+ "the \"get_vnfs\" function.")
+
+ #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.")
+
+ 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.")
diff --git a/core/vnf_controller_p2p.py b/core/vnf_controller_p2p.py
new file mode 100644
index 00000000..60161480
--- /dev/null
+++ b/core/vnf_controller_p2p.py
@@ -0,0 +1,58 @@
+# 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))
diff --git a/core/vnf_controller_pvp.py b/core/vnf_controller_pvp.py
new file mode 100644
index 00000000..16c21869
--- /dev/null
+++ b/core/vnf_controller_pvp.py
@@ -0,0 +1,60 @@
+# 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 = []
+ self._logger.debug('__init__ with ' + str(self._vnf_class))
+ #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._vnf_class))
+ return self._vnfs
+
+ def start(self):
+ """See IVnfController for description
+ """
+ self._logger.debug('start with ' + str(self._vnf_class))
+
+ def stop(self):
+ """See IVnfController for description
+ """
+ self._logger.debug('stop with ' + str(self._vnf_class))
diff --git a/core/vswitch_controller.py b/core/vswitch_controller.py
new file mode 100644
index 00000000..1caf94fb
--- /dev/null
+++ b/core/vswitch_controller.py
@@ -0,0 +1,50 @@
+# 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.
+"""Interface for deployment specific vSwitch controllers
+"""
+
+class IVswitchController(object):
+ """Abstract class which defines a vSwitch controller object
+
+ This interface is used to setup and control a vSwitch provider for a
+ particular deployment scenario.
+ """
+ def setup(self):
+ """Sets up the switch for the particular deployment scenario
+ """
+ raise NotImplementedError(
+ "The VswitchController does not implement the \"setup\" function.")
+ def stop(self):
+ """Tears down the switch created in setup()
+ """
+ raise NotImplementedError(
+ "The VswitchController does not implement the \"stop\" function.")
+
+ def get_vswitch(self):
+ """Get the controlled vSwitch
+
+ :return: The controlled IVswitch
+ """
+ raise NotImplementedError(
+ "The VswitchController does not implement the \"get_vswitch\" "
+ "function.")
+
+ def get_ports_info(self):
+ """Returns a dictionary describing all ports on the vSwitch.
+
+ See IVswitch for dictionary structure details
+ """
+ raise NotImplementedError(
+ "The VswitchController does not implement the \"get_ports_info\" "
+ "function.")
diff --git a/core/vswitch_controller_p2p.py b/core/vswitch_controller_p2p.py
new file mode 100644
index 00000000..ceb29aa9
--- /dev/null
+++ b/core/vswitch_controller_p2p.py
@@ -0,0 +1,90 @@
+# 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 Physical deployment
+"""
+
+import logging
+
+from core.vswitch_controller import IVswitchController
+from vswitches.utils import add_ports_to_flow
+
+_FLOW_TEMPLATE = {
+ 'idle_timeout': '0'
+}
+BRIDGE_NAME = 'br0'
+
+class VswitchControllerP2P(IVswitchController):
+ """VSwitch controller for P2P 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):
+ """Initializes up the prerequisites for the P2P 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 = "P2P"
+ self._logger.debug('Creation using ' + str(self._vswitch_class))
+
+ def setup(self):
+ """Sets up the switch for p2p.
+ """
+ self._logger.debug('Setup using ' + str(self._vswitch_class))
+
+ try:
+ self._vswitch.start()
+
+ self._vswitch.add_switch(BRIDGE_NAME)
+
+ (_, phy1_number) = self._vswitch.add_phy_port(BRIDGE_NAME)
+ (_, phy2_number) = self._vswitch.add_phy_port(BRIDGE_NAME)
+
+ self._vswitch.del_flow(BRIDGE_NAME)
+ flow = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number, phy2_number)
+ self._vswitch.add_flow(BRIDGE_NAME, flow)
+
+ 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(BRIDGE_NAME)
diff --git a/core/vswitch_controller_pvp.py b/core/vswitch_controller_pvp.py
new file mode 100644
index 00000000..c0286323
--- /dev/null
+++ b/core/vswitch_controller_pvp.py
@@ -0,0 +1,69 @@
+# 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
+
+class VswitchControllerPVP(IVswitchController):
+ """VSwitch controller for PVP 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):
+ """Initializes up the prerequisites for the PVP 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 = "PVP"
+ self._logger.debug('Creation using ' + str(self._vswitch_class))
+
+ def setup(self):
+ """
+ Sets up the switch for the particular deployment scenario passed in to
+ the constructor.
+ """
+ # TODO call IVSwitch methods to configure VSwitch for PVP scenario.
+ self._logger.debug('Setup using ' + str(self._vswitch_class))
+
+ def stop(self):
+ """
+ Tears down the switch created in setup().
+ """
+ # TODO call IVSwitch methods to stop VSwitch for PVP scenario.
+ self._logger.debug('Stop using ' + str(self._vswitch_class))
+
+ 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 []
+
+
+