1 # Copyright 2015-2016 Intel Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 """VSPERF VSwitch implementation using DPDK and vhost ports
22 from src.ovs import OFBridge
23 from src.dpdk import dpdk
24 from conf import settings
25 from vswitches.ovs import IVSwitchOvs
27 class OvsDpdkVhost(IVSwitchOvs):
28 """ Open vSwitch with DPDK support
30 Generic OVS wrapper functionality in src.ovs is maximally used. This
31 class wraps DPDK system configuration along with DPDK specific OVS
34 The method docstrings document only considerations specific to this
35 implementation. For generic information of the nature of the methods,
40 super(OvsDpdkVhost, self).__init__()
41 self._logger = logging.getLogger(__name__)
45 # legacy DPDK configuration through --dpdk option of vswitchd
46 if self.old_dpdk_config():
47 vswitchd_args = ['--dpdk'] + settings.getValue('VSWITCHD_DPDK_ARGS')
48 if self._vswitchd_args:
49 self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args
51 self._vswitchd_args = vswitchd_args
53 if settings.getValue('VNF').endswith('Cuse'):
54 self._logger.info("Inserting VHOST Cuse modules into kernel...")
55 dpdk.insert_vhost_modules()
58 """ Configure vswitchd DPDK options through ovsdb if needed
60 dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG')
61 if dpdk_config and not self.old_dpdk_config():
62 # enforce calls to ovs-vsctl with --no-wait
63 tmp_br = OFBridge(timeout=-1)
64 for option in dpdk_config:
65 tmp_br.set_db_attribute('Open_vSwitch', '.',
66 'other_config:' + option, dpdk_config[option])
69 """See IVswitch for general description
71 Activates DPDK kernel modules, ovsdb and vswitchd.
74 super(OvsDpdkVhost, self).start()
75 # old style OVS <= 2.5.0 multi-queue enable
76 if settings.getValue('OVS_OLD_STYLE_MQ') and \
77 int(settings.getValue('VSWITCH_MULTI_QUEUES')):
78 tmp_br = OFBridge(timeout=-1)
79 tmp_br.set_db_attribute(
80 'Open_vSwitch', '.', 'other_config:' +
81 'n-dpdk-rxqs', settings.getValue('VSWITCH_MULTI_QUEUES'))
84 """See IVswitch for general description
86 Kills ovsdb and vswitchd and removes DPDK kernel modules.
89 super(OvsDpdkVhost, self).stop()
91 dpdk.remove_vhost_modules()
93 def add_switch(self, switch_name, params=None):
94 """See IVswitch for general description
96 switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
98 switch_params = switch_params + params
100 super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
101 if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
102 # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
103 # for CPU core affinitization
104 self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.',
105 'other_config:pmd-cpu-mask',
106 settings.getValue('VSWITCH_PMD_CPU_MASK'))
108 def add_phy_port(self, switch_name):
109 """See IVswitch for general description
111 Creates a port of type dpdk.
112 The new port is named dpdk<n> where n is an integer starting from 0.
114 bridge = self._bridges[switch_name]
115 dpdk_count = self._get_port_count('type=dpdk')
116 port_name = 'dpdk' + str(dpdk_count)
117 params = ['--', 'set', 'Interface', port_name, 'type=dpdk']
119 if int(settings.getValue('VSWITCH_MULTI_QUEUES')) and \
120 not settings.getValue('OVS_OLD_STYLE_MQ'):
121 params += ['options:n_rxq={}'.format(
122 settings.getValue('VSWITCH_MULTI_QUEUES'))]
123 of_port = bridge.add_port(port_name, params)
124 return (port_name, of_port)
126 def add_vport(self, switch_name):
127 """See IVswitch for general description
129 Creates a port of type dpdkvhost
130 The new port is named dpdkvhost<n> where n is an integer starting
133 bridge = self._bridges[switch_name]
134 # Changed dpdkvhost to dpdkvhostuser to be able to run in Qemu 2.2
135 if settings.getValue('VNF').endswith('Cuse'):
136 vhost_count = self._get_port_count('type=dpdkvhostcuse')
137 port_name = 'dpdkvhostcuse' + str(vhost_count)
138 params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostcuse']
140 vhost_count = self._get_port_count('type=dpdkvhostuser')
141 port_name = 'dpdkvhostuser' + str(vhost_count)
142 params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
144 if int(settings.getValue('VSWITCH_MULTI_QUEUES')) and \
145 not settings.getValue('OVS_OLD_STYLE_MQ'):
146 params += ['options:n_rxq={}'.format(
147 settings.getValue('VSWITCH_MULTI_QUEUES'))]
148 of_port = bridge.add_port(port_name, params)
150 return (port_name, of_port)
153 def old_dpdk_config():
154 """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
156 :returns: True if legacy --dpdk option is supported, otherwise it returns False
159 ovs_vswitchd_bin = os.path.join(settings.getValue('OVS_DIR'), 'vswitchd', 'ovs-vswitchd')
161 subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
163 except subprocess.CalledProcessError: