aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/02_vswitch.conf4
-rw-r--r--docs/NEWS.md6
-rwxr-xr-xdocs/quickstart.md7
-rw-r--r--src/Makefile6
-rwxr-xr-xsrc/dpdk/Makefile12
-rw-r--r--src/dpdk/dpdk.py26
-rwxr-xr-xsrc/ovs/Makefile26
-rw-r--r--src/ovs/daemon.py32
-rwxr-xr-xtest_spec/vswitchperf_ltd.md75
-rw-r--r--tools/module_manager.py97
-rw-r--r--vswitches/ovs_dpdk_vhost.py3
-rw-r--r--vswitches/ovs_vanilla.py132
12 files changed, 381 insertions, 45 deletions
diff --git a/conf/02_vswitch.conf b/conf/02_vswitch.conf
index 8b6a80a0..48bf5964 100644
--- a/conf/02_vswitch.conf
+++ b/conf/02_vswitch.conf
@@ -38,6 +38,10 @@ BLACKLIST_NICS = ['0000:09:00.0', '0000:09:00.1', '0000:09:00.2',
# hardware configuration, like cpu numbering and NUMA.
VSWITCHD_DPDK_ARGS = ['-c', '0x4', '-n', '4', '--socket-mem 1024,0']
+VSWITCHD_VANILLA_ARGS = ['--pidfile']
+VSWITCH_VANILLA_PHY_PORT_NAMES = ['', '']
+VSWITCH_VANILLA_KERNEL_MODULES = ['openvswitch']
+
# directory where hugepages will be mounted on system init
HUGEPAGE_DIR = '/dev/hugepages'
diff --git a/docs/NEWS.md b/docs/NEWS.md
index 892bfabf..0e322580 100644
--- a/docs/NEWS.md
+++ b/docs/NEWS.md
@@ -10,6 +10,12 @@ once the community has digested the initial release.
## New
* Performance testing with continuous stream
+* Vanilla OVS support added.
+ * Support for non-DPDK OVS build.
+ * Build and installation support through Makefile will be added via
+ next patch(Currently it is possible to manually build ovs and
+ setting it in vsperf configuration files).
+ * PvP scenario is not yet implemented.
* CentOS7 support
* Verified on CentOS7
* Install & Quickstart documentation
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 9ab15c15..45bca6c5 100755
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -29,6 +29,13 @@ cd src
make
```
+VSPERF can be used with OVS without DPDK support. In this case you have to specify path to the kernel sources by WITH_LINUX parameter:
+
+```bash
+cd src
+make WITH_LINUX=/lib/modules/`uname -r`/build
+```
+
To delete a src subdirectory and its contents to allow you to re-clone simply use:
```bash
diff --git a/src/Makefile b/src/Makefile
index 496b717b..0b62da3e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -21,14 +21,20 @@
include mk/master.mk
+export VHOST_USER
+
# specify upstream package as SUBDIRS - common terms as suggest by gnu-make
SUBDIRS =
SUBDIRS += l2fwd
+ifeq ($(WITH_LINUX),)
SUBDIRS += dpdk
+endif
SUBDIRS += ovs
SUBDIRS += qemu
+ifeq ($(WITH_LINUX),)
# specify package dependency here if needed
ovs: dpdk
+endif
include mk/make-subsys.mk
diff --git a/src/dpdk/Makefile b/src/dpdk/Makefile
index 1f4ca0ae..8335ed4e 100755
--- a/src/dpdk/Makefile
+++ b/src/dpdk/Makefile
@@ -24,6 +24,9 @@ include ../package-list.mk
.PHONY: install force_make
+ifndef VHOST_USER
+ VHOST_USER = n
+endif
WORK_DIR = dpdk
TAG_DONE_FLAG = $(WORK_DIR)/.$(DPDK_TAG).tag.done
@@ -41,8 +44,14 @@ all: force_make
INSTALL_TARGET = force_make
+# modify CONFIG_FILE to enable VHOST_USER build and restore original CONFIG_FILE after the build
force_make: $(TAG_DONE_FLAG)
+ $(AT)sed -i -e 's/CONFIG_RTE_LIBRTE_VHOST_USER=.\+/CONFIG_RTE_LIBRTE_VHOST_USER=$(VHOST_USER)/g' $(CONFIG_FILE)
+ $(AT)sed -i -e 's/CONFIG_RTE_BUILD_COMBINE_LIBS=./CONFIG_RTE_BUILD_COMBINE_LIBS=y/g' $(CONFIG_FILE)
+ $(AT)sed -i -e 's/CONFIG_RTE_LIBRTE_VHOST=./CONFIG_RTE_LIBRTE_VHOST=y/g' $(CONFIG_FILE)
+ $(AT)sed -i -e 's/CONFIG_RTE_LIBRTE_KNI=./CONFIG_RTE_LIBRTE_KNI=n/g' $(CONFIG_FILE)
$(AT)cd $(WORK_DIR); make install T=$(DPDK_TARGET) -j
+ $(AT)cd `dirname $(CONFIG_FILE)` && git checkout `basename $(CONFIG_FILE)` && cd -
@echo "Make done"
install: $(INSTALL_TARGET)
@@ -70,7 +79,4 @@ $(WORK_DIR):
$(TAG_DONE_FLAG): $(WORK_DIR)
$(AT)cd $(WORK_DIR); git checkout $(DPDK_TAG)
- $(AT)sed -i 's/CONFIG_RTE_BUILD_COMBINE_LIBS=n/CONFIG_RTE_BUILD_COMBINE_LIBS=y/g' $(CONFIG_FILE)
- $(AT)sed -i 's/CONFIG_RTE_LIBRTE_VHOST=n/CONFIG_RTE_LIBRTE_VHOST=y/g' $(CONFIG_FILE)
- $(AT)sed -i 's/CONFIG_RTE_LIBRTE_KNI=y /CONFIG_RTE_LIBRTE_KNI=n/g' $(CONFIG_FILE)
$(AT)touch $@
diff --git a/src/dpdk/dpdk.py b/src/dpdk/dpdk.py
index 9b3d1385..01e1fb61 100644
--- a/src/dpdk/dpdk.py
+++ b/src/dpdk/dpdk.py
@@ -27,11 +27,14 @@ import locale
from tools import tasks
from conf import settings
+from tools.module_manager import ModuleManager, KernelModuleInsertMode
_LOGGER = logging.getLogger(__name__)
RTE_PCI_TOOL = os.path.join(
settings.getValue('RTE_SDK'), 'tools', 'dpdk_nic_bind.py')
+_DPDK_MODULE_MANAGER = ModuleManager(KernelModuleInsertMode.MODPROBE)
+
#
# system management
#
@@ -192,16 +195,8 @@ def _is_module_inserted(module):
def _insert_modules():
"""Ensure required modules are inserted on system.
"""
- for module in settings.getValue('SYS_MODULES'):
- if _is_module_inserted(module):
- continue
- try:
- tasks.run_task(['sudo', 'modprobe', module], _LOGGER,
- 'Inserting module \'%s\'...' % module, True)
- except subprocess.CalledProcessError:
- _LOGGER.error('Unable to insert module \'%s\'.', module)
- raise # fail catastrophically
+ _DPDK_MODULE_MANAGER.insert_modules(settings.getValue('SYS_MODULES'))
mod_path_prefix = settings.getValue('OVS_DIR')
_insert_module_group('OVS_MODULES', mod_path_prefix)
@@ -237,18 +232,7 @@ def _remove_modules():
_remove_module_group('OVS_MODULES')
_remove_module_group('DPDK_MODULES')
- for module in settings.getValue('SYS_MODULES'):
- # first check if module is loaded
- if not _is_module_inserted(module):
- continue
-
- try:
- tasks.run_task(['sudo', 'rmmod', module], _LOGGER,
- 'Removing module \'%s\'...' % module, True)
- except subprocess.CalledProcessError:
- _LOGGER.error('Unable to remove module \'%s\'.', module)
- continue
-
+ _DPDK_MODULE_MANAGER.remove_modules()
def _remove_module_group(module_group):
"""Ensure all modules in a group are removed from the system.
diff --git a/src/ovs/Makefile b/src/ovs/Makefile
index 68ac0f6d..223d2dcb 100755
--- a/src/ovs/Makefile
+++ b/src/ovs/Makefile
@@ -22,11 +22,26 @@
include ../mk/master.mk
include ../package-list.mk
+WORK_DIR = ovs
+TAG_DONE_FLAG = $(WORK_DIR)/.$(OVS_TAG).done
+CONFIG_CMD =
+CONFIG_CMD += ./configure
+
+# If WITH_LINUX is defined, OVS is built without DPDK but with kernel
+# module
+# By default, OVS is built with DPDK
+
+# WITH_LINUX is the Linux kernel build directory used for building
+# OVS kernel module as documented in OVS --with-linux switch
+ifneq ($(WITH_LINUX),) # Building with Linux kernel
+CONFIG_CMD += --with-linux=$(WITH_LINUX)
+
+else # Building with DPDK
+
# DPDK_DIR is the top directory for dpdk source tree
# it can be passed in from Makefile command
# if it is not set, try to read it in from environment
# if it is still not set, then set it using relative path
-
DPDK_DIR ?= $(shell echo $$DPDK_DIR)
ifeq ($(DPDK_DIR),)
DPDK_DIR = ../../dpdk/dpdk
@@ -35,20 +50,15 @@ endif
ifeq ($(DPDK_TARGET),)
DPDK_TARGET = x86_64-native-linuxapp-gcc
endif
+CONFIG_CMD += --with-dpdk=$(DPDK_DIR)/$(DPDK_TARGET)
+endif # Kernel vs. DPDK
.PHONY: install force_install config force_make
# install depends on make
force_install: force_make
-WORK_DIR = ovs
-TAG_DONE_FLAG = $(WORK_DIR)/.$(OVS_TAG).done
-CONFIG_CMD =
-CONFIG_CMD += ./configure
-CONFIG_CMD += --with-dpdk=$(DPDK_DIR)/$(DPDK_TARGET)
-
-
all: force_make
@echo "Finished making $(WORK_DIR) "
diff --git a/src/ovs/daemon.py b/src/ovs/daemon.py
index 323644c6..db096353 100644
--- a/src/ovs/daemon.py
+++ b/src/ovs/daemon.py
@@ -44,12 +44,12 @@ class VSwitchd(tasks.Process):
"""
_ovsdb_pid = None
_logfile = _LOG_FILE_VSWITCHD
+ _ovsdb_pidfile_path = os.path.join(settings.getValue('LOG_DIR'),
+ "ovsdb_pidfile.pid")
-
- _expect = r'EAL: Master l*core \d+ is ready'
_proc_name = 'ovs-vswitchd'
- def __init__(self, timeout=30, vswitchd_args=None):
+ def __init__(self, timeout=30, vswitchd_args=None, expected_cmd=None):
"""Initialise the wrapper with a specific start timeout and extra
parameters.
@@ -60,8 +60,8 @@ class VSwitchd(tasks.Process):
"""
self._logger = logging.getLogger(__name__)
self._timeout = timeout
+ self._expect = expected_cmd;
vswitchd_args = vswitchd_args or []
-
self._cmd = ['sudo', '-E', _OVS_VSWITCHD_BIN] + vswitchd_args
# startup/shutdown
@@ -72,6 +72,7 @@ class VSwitchd(tasks.Process):
:returns: None
:raises: pexpect.EOF, pexpect.TIMEOUT
"""
+
self._reset_ovsdb()
self._start_ovsdb() # this has to be started first
@@ -79,6 +80,7 @@ class VSwitchd(tasks.Process):
super(VSwitchd, self).start()
self.relinquish()
except (pexpect.EOF, pexpect.TIMEOUT) as exc:
+ logging.error("Exception during VSwitch start.")
self._kill_ovsdb()
raise exc
@@ -125,10 +127,11 @@ class VSwitchd(tasks.Process):
self._logger,
'Creating ovsdb configuration database...')
- self._ovsdb_pid = tasks.run_background_task(
+ tasks.run_background_task(
['sudo', _OVSDB_SERVER_BIN,
'--remote=punix:%s' % os.path.join(_OVS_VAR_DIR, 'db.sock'),
- '--remote=db:Open_vSwitch,Open_vSwitch,manager_options'],
+ '--remote=db:Open_vSwitch,Open_vSwitch,manager_options',
+ '--pidfile=' + self._ovsdb_pidfile_path , '--overwrite-pidfile'],
self._logger,
'Starting ovsdb-server...')
@@ -137,6 +140,19 @@ class VSwitchd(tasks.Process):
:returns: None
"""
- if self._ovsdb_pid:
- tasks.run_task(['sudo', 'kill', '-15', str(self._ovsdb_pid)],
+ with open (self._ovsdb_pidfile_path, "r") as pidfile:
+ ovsdb_pid = pidfile.read().strip()
+
+ self._logger.info("Killing ovsdb with pid: " + ovsdb_pid)
+
+ if ovsdb_pid:
+ tasks.run_task(['sudo', 'kill', '-15', str(ovsdb_pid)],
self._logger, 'Killing ovsdb-server...')
+
+ @staticmethod
+ def getDbSockPath():
+ """Method returns location of db.sock file
+
+ :returns: path to db.sock file.
+ """
+ return os.path.join(_OVS_VAR_DIR, 'db.sock')
diff --git a/test_spec/vswitchperf_ltd.md b/test_spec/vswitchperf_ltd.md
index 07d49dc9..4aec9b80 100755
--- a/test_spec/vswitchperf_ltd.md
+++ b/test_spec/vswitchperf_ltd.md
@@ -808,7 +808,7 @@ The starting point for defining the suite of tests for benchmarking the performa
**Description**:
- The aim of this test is to characterize the ability of the DUT to process back-to-back frames. For each frame size previously defined under [Default Test Parameters](#DefaultParams), a burst of traffic is sent to the DUT with the minimum inter-frame gap between each frame. If the number of received frames equals the number of frames that were transmitted, the burst size should be increased and traffic is sent to the DUT again. The value measured is the back-to-back value, that is the maximum burst size the DUT can handle without any frame loss.
+ The aim of this test is to characterize the ability of the DUT to process back-to-back frames. For each frame size previously defined under [Default Test Parameters](#DefaultParams), a burst of traffic is sent to the DUT with the minimum inter-frame gap between each frame. If the number of received frames equals the number of frames that were transmitted, the burst size should be increased and traffic is sent to the DUT again. The value measured is the back-to-back value, that is the maximum burst size the DUT can handle without any frame loss.
**Expected Result**:
@@ -1103,13 +1103,24 @@ The starting point for defining the suite of tests for benchmarking the performa
The aim of this test is to determine the maximum forwarding rate of the DUT when forwarding broadcast traffic. For each frame previously defined under [Default Test Parameters](#DefaultParams), the traffic should be set up as broadcast traffic. The traffic throughput of the DUT should be measured.
+ The test should be conducted with at least 4 physical ports on the DUT. The number of ports used MUST be recorded.
+
+ As broadcast involves forwarding a single incoming packet to several destinations, the latency of a single packet is defined as the average of the latencies for each of the broadcast destinations.
+
+ The incoming packet is transmitted on each of the other physical ports, it is not transmitted on the port on which it was received. The test MAY be conducted using different broadcasting ports to uncover any performance differences.
+
**Expected Result**:
- **Metrics collected**
+ **Metrics collected**:
The following are the metrics collected for this test:
- The forwarding rate of the DUT when forwarding broadcast traffic.
+ - The minimum, average & maximum packets latencies observed.
+
+ **Deployment scenario**:
+
+ - Physical → virtual switch 3x physical.
<br/>
- #####Test ID: LTD.MemoryBandwidth.RFC2544.0PacketLoss.Scalability
@@ -1149,13 +1160,19 @@ The starting point for defining the suite of tests for benchmarking the performa
- #####Test ID: LTD.PacketLatency.InitialPacketProcessingLatency
**Title**: Initial Packet Processing Latency
- **Prerequisite Test**: N\A
+ **Prerequisite Test**: N\A
**Priority**:
**Description**:
- In some virtual switch architectures, the first packets of a flow will take the system longer to process than subsequent packets in the flow. This test determines the latency for these packets. The test will measure the latency of the packets as they are processed by the flow-setup-path of the DUT. This test will send a single packet to the DUT after a fixed interval of time. The time interval will be equivalent to the amount of time it takes for a flow to time out in the virtual switch. Average packet latency will be determined over 1,000,000 packets.
+ In some virtual switch architectures, the first packets of a flow will take the system longer to process than subsequent packets in the flow. This test determines the latency for these packets. The test will measure the latency of the packets as they are processed by the flow-setup-path of the DUT. There are two methods for this test, a recommended method and a nalternative method that can be used if it is possible to disable the fastpath of the virtual switch.
+
+ Recommended method: This test will send 64,000 packets to the DUT, each belonging to a different flow. Average packet latency will be determined over the 64,000 packets.
+
+ Alternative method: This test will send a single packet to the DUT after a fixed interval of time. The time interval will be equivalent to the amount of time it takes for a flow to time out in the virtual switch plus 10%. Average packet latency will be determined over 1,000,000 packets.
+
+ This test is intended only for non-learning switches; For learning switches use RFC2889.
For this test, only unidirectional traffic is required.
@@ -1237,6 +1254,56 @@ The starting point for defining the suite of tests for benchmarking the performa
- The maximum number of frames per second that can be forwarded at the specified number of flows and the specified frame size, with zero packet loss.
<br/>
+----
+<a name="CPDPTests"></a>
+#####2.3.5 Coupling between control path and datapath Tests
+
+ The following tests aim to determine how tightly coupled the datapath and the control path are within a virtual switch.
+
+ The following list is not exhaustive but should indicate the type of tests that should be required. It is expected that more will be added.
+
+ - #####Test ID: LTD.CPDPCouplingFlowAddition
+ **Title**: Control Path and Datapath Coupling
+
+ **Prerequisite Test**:
+
+ **Priority**:
+
+ **Description**:
+
+ The aim of this test is to understand how exercising the DUT's control path affects datapath performance.
+
+ Initially a certain number of flow table entries are installed in the vSwitch. Then over the duration of an RFC2544 throughput test flow-entries are added and removed at the rates specified below. No traffic is 'hitting' these flow-entries, they are simply added and removed.
+
+ The test MUST be repeated with the following initial number of flow-entries installed:
+ - < 10
+ - 1000
+ - 100,000
+ - 10,000,000 (or the maximum supported number of flow-entries)
+
+ The test MUST be repeated with the following rates of flow-entry addition and deletion per second:
+ - 0
+ - 1 (i.e. 1 addition plus 1 deletion)
+ - 100
+ - 10,000
+
+ **Expected Result**:
+
+ **Metrics Collected**:
+
+ The following are the metrics collected for this test:
+
+ - The maximum forwarding rate in Frames Per Second (FPS) and Mbps of the DUT.
+ - The average latency of the traffic flow when passing through the DUT (if testing for latency, note that this average is different from the test specified in Section 26.3 of [RFC2544]).
+ - CPU and memory utilization may also be collected as part of this test, to determine the vSwitch's performance footprint on the system.
+
+ **Deployment scenario**:
+
+ - Physical → virtual switch → physical.
+
+
+<br/>
+
<a name="SummaryList"></a>
####2.3.9 Summary List of Tests
diff --git a/tools/module_manager.py b/tools/module_manager.py
new file mode 100644
index 00000000..6ed80e93
--- /dev/null
+++ b/tools/module_manager.py
@@ -0,0 +1,97 @@
+# 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.
+
+"""Simple kernel module manager implementation.
+"""
+
+import subprocess
+import logging
+from tools import tasks
+
+class KernelModuleInsertMode(object):
+ """Module manager type of insert definition.
+ """
+ MODPROBE = 1
+ INSMOD = 2 #NOT IMPLEMENTED
+
+class ModuleManager(object):
+ """Simple module manager which acts as system wrapper for Kernel Modules.
+ """
+
+ _logger = logging.getLogger(__name__)
+
+ def __init__(self, insert_mode=KernelModuleInsertMode.MODPROBE):
+ """Initializes data and sets insert mode.
+
+ :param insert_mode: insert mode defines how modules are going to
+ be inserted in system.
+ """
+ self._modules = None
+ self._insert_mode = insert_mode
+
+ def insert_modules(self, modules):
+ """Method inserts list of modules using defined insert mode.
+
+ :param modules: list of modules to be inserted. Each element on
+ list should represent format which is expected
+ by KernelModuleInsertMode (e.g. for MODPROBE it
+ would be module name).
+
+ :returns: None
+ """
+ self._modules = modules
+ for module in modules:
+ if ModuleManager.is_module_inserted(module):
+ continue
+
+ try:
+ if self._insert_mode == KernelModuleInsertMode.MODPROBE:
+ tasks.run_task(['sudo', 'modprobe', module], self._logger,
+ 'Inserting module \'%s\'...' % module, True)
+ else:
+ self._logger.error(
+ "Kernel module insert mode NOT IMPLEMENTED.")
+ raise
+
+ except subprocess.CalledProcessError:
+ self._logger.error('Unable to insert module \'%s\'.', module)
+ raise # fail catastrophically
+
+ def remove_modules(self):
+ """Removes all modules that have been previously instereted.
+ """
+ for module in self._modules:
+ # first check if module is loaded
+ if not ModuleManager.is_module_inserted(module):
+ continue
+
+ try:
+ tasks.run_task(['sudo', 'rmmod', module], self._logger,
+ 'Removing module \'%s\'...' % module, True)
+ except subprocess.CalledProcessError:
+ self._logger.error('Unable to remove module \'%s\'.', module)
+ continue
+
+ @staticmethod
+ def is_module_inserted(module):
+ """Check if a module is inserted on system.
+ """
+ with open('/proc/modules') as mod_file:
+ loaded_mods = mod_file.readlines()
+
+ # first check if module is loaded
+ for line in loaded_mods:
+ if line.startswith(module):
+ return True
+ return False
diff --git a/vswitches/ovs_dpdk_vhost.py b/vswitches/ovs_dpdk_vhost.py
index d2e8907f..7b5034c5 100644
--- a/vswitches/ovs_dpdk_vhost.py
+++ b/vswitches/ovs_dpdk_vhost.py
@@ -38,7 +38,8 @@ class OvsDpdkVhost(IVSwitch):
vswitchd_args += settings.getValue('VSWITCHD_DPDK_ARGS')
vswitchd_args += VSWITCHD_CONST_ARGS
- self._vswitchd = VSwitchd(vswitchd_args=vswitchd_args)
+ self._vswitchd = VSwitchd(vswitchd_args=vswitchd_args,
+ expected_cmd=r'EAL: Master l*core \d+ is ready')
self._bridges = {}
def start(self):
diff --git a/vswitches/ovs_vanilla.py b/vswitches/ovs_vanilla.py
new file mode 100644
index 00000000..a7d4d206
--- /dev/null
+++ b/vswitches/ovs_vanilla.py
@@ -0,0 +1,132 @@
+# 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.
+
+"""VSPERF Vanilla OVS implementation
+"""
+
+import logging
+from conf import settings
+from vswitches.vswitch import IVSwitch
+from src.ovs import VSwitchd, OFBridge
+from tools.module_manager import ModuleManager, KernelModuleInsertMode
+
+VSWITCHD_CONST_ARGS = ['--', '--log-file']
+
+class OvsVanilla(IVSwitch):
+ """VSwitch Vanilla implementation
+
+ This is wrapper for functionality implemented in src.ovs.
+
+ The method docstrings document only considerations specific to this
+ implementation. For generic information of the nature of the methods,
+ see the interface definition.
+ """
+
+ _logger = logging.getLogger()
+ _ports = settings.getValue('VSWITCH_VANILLA_PHY_PORT_NAMES')
+ _current_id = 0
+
+ def __init__(self):
+ #vswitchd_args = VSWITCHD_CONST_ARGS
+ vswitchd_args = ["unix:%s" % VSwitchd.getDbSockPath()]
+ vswitchd_args += settings.getValue('VSWITCHD_VANILLA_ARGS')
+ self._vswitchd = VSwitchd(vswitchd_args=vswitchd_args,
+ expected_cmd="db.sock: connected")
+ self._bridges = {}
+ self._module_manager = ModuleManager(KernelModuleInsertMode.MODPROBE)
+
+ def start(self):
+ """See IVswitch for general description
+
+ Activates kernel modules, ovsdb and vswitchd.
+ """
+ self._module_manager.insert_modules(
+ settings.getValue('VSWITCH_VANILLA_KERNEL_MODULES'))
+ self._logger.info("Starting Vswitchd...")
+ self._vswitchd.start()
+ self._logger.info("Vswitchd...Started.")
+
+ def stop(self):
+ """See IVswitch for general description
+
+ Kills ovsdb and vswitchd and removes kernel modules.
+ """
+ self._vswitchd.kill()
+ self._module_manager.remove_modules()
+
+ def add_switch(self, switch_name):
+ """See IVswitch for general description
+ """
+ bridge = OFBridge(switch_name)
+ bridge.create()
+ bridge.set_db_attribute('Open_vSwitch', '.',
+ 'other_config:max-idle', '60000')
+ self._bridges[switch_name] = bridge
+
+ def del_switch(self, switch_name):
+ """See IVswitch for general description
+ """
+ bridge = self._bridges[switch_name]
+ self._bridges.pop(switch_name)
+ bridge.destroy()
+
+ def add_phy_port(self, switch_name):
+ """
+ Method adds port based on configured VSWITCH_VANILLA_PHY_PORT_NAMES
+ stored in config file.
+
+ See IVswitch for general description
+ """
+ if self._current_id == len(self._ports):
+ self._logger.error("Can't add port! There are only " +
+ len(self._ports) + " ports " +
+ "defined in config!")
+ raise
+
+ bridge = self._bridges[switch_name]
+ port_name = self._ports[self._current_id]
+ params = []
+ of_port = bridge.add_port(port_name, params)
+ self._current_id += 1
+ return (port_name, of_port)
+
+ def add_vport(self, switch_name):
+ """See IVswitch for general description"""
+ raise NotImplementedError("Not implemented for Vanilla OVS.")
+
+ def get_ports(self, switch_name):
+ """See IVswitch for general description
+ """
+ bridge = self._bridges[switch_name]
+ ports = list(bridge.get_ports().items())
+ return [(name, of_port) for (name, (of_port, _)) in ports]
+
+ def del_port(self, switch_name, port_name):
+ """See IVswitch for general description
+ """
+ bridge = self._bridges[switch_name]
+ bridge.del_port(port_name)
+
+ def add_flow(self, switch_name, flow):
+ """See IVswitch for general description
+ """
+ bridge = self._bridges[switch_name]
+ bridge.add_flow(flow)
+
+ def del_flow(self, switch_name, flow=None):
+ """See IVswitch for general description
+ """
+ flow = flow or {}
+ bridge = self._bridges[switch_name]
+ bridge.del_flow(flow)