1 # Copyright 2015-2017 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
21 from src.ovs import OFBridge
22 from src.dpdk import dpdk
23 from conf import settings
24 from vswitches.ovs import IVSwitchOvs
26 class OvsDpdkVhost(IVSwitchOvs):
27 """ Open vSwitch with DPDK support
29 Generic OVS wrapper functionality in src.ovs is maximally used. This
30 class wraps DPDK system configuration along with DPDK specific OVS
33 The method docstrings document only considerations specific to this
34 implementation. For generic information of the nature of the methods,
39 super(OvsDpdkVhost, self).__init__()
40 self._logger = logging.getLogger(__name__)
44 # legacy DPDK configuration through --dpdk option of vswitchd
45 if self.old_dpdk_config():
46 vswitchd_args = ['--dpdk'] + settings.getValue('VSWITCHD_DPDK_ARGS')
47 if self._vswitchd_args:
48 self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args
50 self._vswitchd_args = vswitchd_args
53 """ Configure vswitchd DPDK options through ovsdb if needed
55 dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG')
56 if dpdk_config and not self.old_dpdk_config():
57 # enforce calls to ovs-vsctl with --no-wait
58 tmp_br = OFBridge(timeout=-1)
59 for option in dpdk_config:
60 tmp_br.set_db_attribute('Open_vSwitch', '.',
61 'other_config:' + option, dpdk_config[option])
64 """See IVswitch for general description
66 Activates DPDK kernel modules, ovsdb and vswitchd.
69 super(OvsDpdkVhost, self).start()
70 # old style OVS <= 2.5.0 multi-queue enable
71 if settings.getValue('OVS_OLD_STYLE_MQ') and \
72 int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')):
73 tmp_br = OFBridge(timeout=-1)
74 tmp_br.set_db_attribute(
75 'Open_vSwitch', '.', 'other_config:' +
76 'n-dpdk-rxqs', settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))
79 """See IVswitch for general description
81 Kills ovsdb and vswitchd and removes DPDK kernel modules.
84 super(OvsDpdkVhost, self).stop()
87 def add_switch(self, switch_name, params=None):
88 """See IVswitch for general description
90 switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
92 switch_params = switch_params + params
94 super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
95 if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
96 # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
97 # for CPU core affinitization
98 self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.',
99 'other_config:pmd-cpu-mask',
100 settings.getValue('VSWITCH_PMD_CPU_MASK'))
102 def add_phy_port(self, switch_name):
103 """See IVswitch for general description
105 Creates a port of type dpdk.
106 The new port is named dpdk<n> where n is an integer starting from 0.
108 bridge = self._bridges[switch_name]
109 dpdk_count = self._get_port_count('type=dpdk')
110 port_name = 'dpdk' + str(dpdk_count)
111 # PCI info. Please note there must be no blank space, eg must be
112 # like 'options:dpdk-devargs=0000:06:00.0'
113 _nics = settings.getValue('NICS')
114 nic_pci = 'options:dpdk-devargs=' + _nics[dpdk_count]['pci']
115 params = ['--', 'set', 'Interface', port_name, 'type=dpdk', nic_pci]
118 if int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
119 not settings.getValue('OVS_OLD_STYLE_MQ'):
120 params += ['options:n_rxq={}'.format(
121 settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
122 of_port = bridge.add_port(port_name, params)
123 return (port_name, of_port)
125 def add_vport(self, switch_name):
126 """See IVswitch for general description
128 Creates a port of type dpdkvhost
129 The new port is named dpdkvhost<n> where n is an integer starting
132 bridge = self._bridges[switch_name]
133 vhost_count = self._get_port_count('type=dpdkvhostuser')
134 port_name = 'dpdkvhostuser' + str(vhost_count)
135 params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
136 of_port = bridge.add_port(port_name, params)
138 return (port_name, of_port)
141 def old_dpdk_config():
142 """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
144 :returns: True if legacy --dpdk option is supported, otherwise it returns False
147 ovs_vswitchd_bin = settings.getValue('TOOLS')['ovs-vswitchd']
149 subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
151 except subprocess.CalledProcessError: