diff options
Diffstat (limited to 'vswitches')
-rw-r--r-- | vswitches/__init__.py | 20 | ||||
-rw-r--r-- | vswitches/ovs_dpdk_vhost.py | 143 | ||||
-rw-r--r-- | vswitches/utils.py | 40 | ||||
-rw-r--r-- | vswitches/vswitch.py | 114 |
4 files changed, 317 insertions, 0 deletions
diff --git a/vswitches/__init__.py b/vswitches/__init__.py new file mode 100644 index 00000000..a34475be --- /dev/null +++ b/vswitches/__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. + +"""Package for vswitch wrappers for use with VSPERF. + +This package contains an interface the VSPERF core uses for controlling +vSwitches and vSwitch-specific implementation modules of this interface. +""" + diff --git a/vswitches/ovs_dpdk_vhost.py b/vswitches/ovs_dpdk_vhost.py new file mode 100644 index 00000000..d2e8907f --- /dev/null +++ b/vswitches/ovs_dpdk_vhost.py @@ -0,0 +1,143 @@ +# 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 VSwitch implementation using DPDK and vhost ports +""" + +from conf import settings +from vswitches.vswitch import IVSwitch +from src.ovs import VSwitchd, OFBridge +from src.dpdk import dpdk + +VSWITCHD_CONST_ARGS = ['--', '--log-file'] + +class OvsDpdkVhost(IVSwitch): + """VSwitch implementation using DPDK and vhost ports + + Generic OVS wrapper functionality in src.ovs is maximally used. This + class wraps DPDK system configuration along with DPDK specific OVS + parameters + + The method docstrings document only considerations specific to this + implementation. For generic information of the nature of the methods, + see the interface. + """ + def __init__(self): + vswitchd_args = ['--dpdk'] + vswitchd_args += settings.getValue('VSWITCHD_DPDK_ARGS') + vswitchd_args += VSWITCHD_CONST_ARGS + + self._vswitchd = VSwitchd(vswitchd_args=vswitchd_args) + self._bridges = {} + + def start(self): + """See IVswitch for general description + + Activates DPDK kernel modules, ovsdb and vswitchd. + """ + dpdk.init() + self._vswitchd.start() + + def stop(self): + """See IVswitch for general description + + Kills ovsdb and vswitchd and removes DPDK kernel modules. + """ + self._vswitchd.kill() + dpdk.cleanup() + + 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') + bridge.set_db_attribute('Bridge', bridge.br_name, + 'datapath_type', 'netdev') + 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): + """See IVswitch for general description + + Creates a port of type dpdk. + The new port is named dpdk<n> where n is an integer starting from 0. + """ + bridge = self._bridges[switch_name] + dpdk_count = self._get_port_count(bridge, 'type=dpdk') + port_name = 'dpdk' + str(dpdk_count) + params = ['--', 'set', 'Interface', port_name, 'type=dpdk'] + of_port = bridge.add_port(port_name, params) + + return (port_name, of_port) + + def add_vport(self, switch_name): + """See IVswitch for general description + + Creates a port of type dpdkvhost + The new port is named dpdkvhost<n> where n is an integer starting + from 0 + """ + bridge = self._bridges[switch_name] + vhost_count = self._get_port_count(bridge, 'type=dpdkvhost') + port_name = 'dpdkvhost' + str(vhost_count) + params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhost'] + of_port = bridge.add_port(port_name, params) + + return (port_name, of_port) + + 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) + + @staticmethod + def _get_port_count(bridge, param): + """Returns the number of ports having a certain parameter + + :param bridge: The src.ovs.ofctl.OFBridge on which to operate + :param param: The parameter to search for + :returns: Count of matches + """ + port_params = [c for (_, (_, c)) in list(bridge.get_ports().items())] + param_hits = [i for i in port_params if param in i] + return len(param_hits) diff --git a/vswitches/utils.py b/vswitches/utils.py new file mode 100644 index 00000000..7350de31 --- /dev/null +++ b/vswitches/utils.py @@ -0,0 +1,40 @@ +# 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. + +"""Utility functions for working with vSwitches and flows +""" + +import copy + +def add_ports_to_flow(flow, in_port, out_port): + """Creates a new flow based on the given flow and adds in port and out port + to it. + + The flow dictionary structure is described in IVswitch + + :param flow: Description of the flow as a dictionary + :param in_port: OpenFlow number of the ingress port for the rule + :param out_port: OpenFlow number of the eggress port for the rule + + :returns: A new dictionary describing a flow combining the parameters + """ + new_flow = copy.deepcopy(flow) + new_flow['in_port'] = in_port + + if 'actions' in new_flow: + new_flow['actions'].append('output:' + str(out_port)) + else: + new_flow['actions'] = ['output:' + str(out_port)] + + return new_flow diff --git a/vswitches/vswitch.py b/vswitches/vswitch.py new file mode 100644 index 00000000..713974ae --- /dev/null +++ b/vswitches/vswitch.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. + +"""Generic interface VSPERF uses for controlling a vSwitch +""" + +class IVSwitch(object): + """Interface class that is implemented by vSwitch-specific classes + + Other methods are called only between start() and stop() + """ + def start(self): + """Start the vSwitch + + If vSwitch is split to multiple processes, has kernel modules etc., + this is expected to set them all up in correct sequence + """ + raise NotImplementedError() + + def stop(self): + """Stop the vSwitch + + If vSwitch is split to multiple processes, has kernel modules etc., + this is expected to terminate and clean all of them in correct sequence + """ + raise NotImplementedError() + + def add_switch(self, switch_name): + """Create a new logical switch with no ports + + :param switch_name: The name of the new logical switch + :returns: None + """ + raise NotImplementedError() + + def del_switch(self, switch_name): + """Destroy the given logical switch + + :param switch_name: The name of the logical switch to be destroyed + :returns: None + """ + raise NotImplementedError() + + def add_phy_port(self, switch_name): + """Create a new port to the logical switch that is attached to a + physical port + + :param switch_name: The switch where the port is attached to + :returns: (port name, OpenFlow port number) + """ + raise NotImplementedError() + + def add_vport(self, switch_name): + """Create a new port to the logical switch for VM connections + + :param switch_name: The switch where the port is attached to + :returns: (port name, OpenFlow port number) + """ + raise NotImplementedError() + + def get_ports(self, switch_name): + """Return a list of tuples describing the ports of the logical switch + + :param switch_name: The switch whose ports to return + :returns: [(port name, OpenFlow port number), ...] + """ + raise NotImplementedError() + + def del_port(self, switch_name, port_name): + """Delete the port from the logical switch + + The port can be either physical or virtual + + :param switch_name: The switch on which to operate + :param port_name: The port to delete + """ + raise NotImplementedError() + + def add_flow(self, switch_name, flow): + """Add a flow rule to the logical switch + + :param switch_name: The switch on which to operate + :param flow: Flow description as a dictionary + + Example flow dictionary: + flow = { + 'in_port': '1', + 'idle_timeout': '0', + 'actions': ['output:3'] + } + """ + raise NotImplementedError() + + def del_flow(self, switch_name, flow=None): + """Delete the flow rule from the logical switch + + :param switch_name: The switch on which to operate + :param flow: Flow description as a dictionary + + For flow dictionary description, see add_flow + For flow==None, all flows are deleted + """ + raise NotImplementedError() |