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 as S
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 # override socket-mem settings
47 tmp_dpdk_args = S.getValue('VSWITCHD_DPDK_ARGS')
48 for tmp_arg in tmp_dpdk_args:
49 if tmp_arg.startswith('--socket-mem'):
50 tmp_dpdk_args.remove(tmp_arg)
51 tmp_dpdk_args += ['--socket-mem ' + ','.join(S.getValue('DPDK_SOCKET_MEM'))]
52 vswitchd_args = ['--dpdk'] + tmp_dpdk_args
53 # add dpdk args to generic ovs-vswitchd settings
54 if self._vswitchd_args:
55 self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args
57 self._vswitchd_args = vswitchd_args
60 """ Configure vswitchd DPDK options through ovsdb if needed
62 dpdk_config = S.getValue('VSWITCHD_DPDK_CONFIG')
63 if dpdk_config and not self.old_dpdk_config():
64 # override socket-mem settings
65 dpdk_config['dpdk-socket-mem'] = ','.join(S.getValue('DPDK_SOCKET_MEM'))
66 # enforce calls to ovs-vsctl with --no-wait
67 tmp_br = OFBridge(timeout=-1)
68 for option in dpdk_config:
69 tmp_br.set_db_attribute('Open_vSwitch', '.',
70 'other_config:' + option, dpdk_config[option])
73 """See IVswitch for general description
75 Activates DPDK kernel modules, ovsdb and vswitchd.
78 super(OvsDpdkVhost, self).start()
79 # old style OVS <= 2.5.0 multi-queue enable
80 if S.getValue('OVS_OLD_STYLE_MQ') and \
81 int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES')):
82 tmp_br = OFBridge(timeout=-1)
83 tmp_br.set_db_attribute(
84 'Open_vSwitch', '.', 'other_config:' +
85 'n-dpdk-rxqs', S.getValue('VSWITCH_DPDK_MULTI_QUEUES'))
88 """See IVswitch for general description
90 Kills ovsdb and vswitchd and removes DPDK kernel modules.
93 super(OvsDpdkVhost, self).stop()
96 def add_switch(self, switch_name, params=None):
97 """See IVswitch for general description
99 switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
101 switch_params = switch_params + params
103 super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
104 if S.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
105 # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
106 # for CPU core affinitization
107 self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.',
108 'other_config:pmd-cpu-mask',
109 S.getValue('VSWITCH_PMD_CPU_MASK'))
111 def add_phy_port(self, switch_name):
112 """See IVswitch for general description
114 Creates a port of type dpdk.
115 The new port is named dpdk<n> where n is an integer starting from 0.
117 _nics = S.getValue('NICS')
118 bridge = self._bridges[switch_name]
119 dpdk_count = self._get_port_count('type=dpdk')
120 if dpdk_count == len(_nics):
121 raise RuntimeError("Can't add phy port! There are only {} ports defined "
122 "by WHITELIST_NICS parameter!".format(len(_nics)))
123 port_name = 'dpdk' + str(dpdk_count)
124 # PCI info. Please note there must be no blank space, eg must be
125 # like 'options:dpdk-devargs=0000:06:00.0'
126 nic_pci = 'options:dpdk-devargs=' + _nics[dpdk_count]['pci']
127 params = ['--', 'set', 'Interface', port_name, 'type=dpdk', nic_pci]
130 if int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
131 not S.getValue('OVS_OLD_STYLE_MQ'):
132 params += ['options:n_rxq={}'.format(
133 S.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
134 if S.getValue('VSWITCH_JUMBO_FRAMES_ENABLED'):
135 params += ['mtu_request={}'.format(
136 S.getValue('VSWITCH_JUMBO_FRAMES_SIZE'))]
137 of_port = bridge.add_port(port_name, params)
138 return (port_name, of_port)
140 def add_vport(self, switch_name):
141 """See IVswitch for general description
143 Creates a port of type dpdkvhost
144 The new port is named dpdkvhost<n> where n is an integer starting
147 bridge = self._bridges[switch_name]
149 if S.getValue('VSWITCH_VHOSTUSER_SERVER_MODE'):
150 nic_type = 'dpdkvhostuser'
152 nic_type = 'dpdkvhostuserclient'
154 vhost_count = self._get_port_count('type={}'.format(nic_type))
155 port_name = nic_type + str(vhost_count)
156 params = ['--', 'set', 'Interface', port_name, 'type={}'.format(nic_type)]
157 if not S.getValue('VSWITCH_VHOSTUSER_SERVER_MODE'):
158 params += ['--', 'set', 'Interface', port_name, 'options:vhost-server-path='
159 '{}{}'.format(S.getValue('TOOLS')['ovs_var_tmp'], port_name)]
160 if S.getValue('VSWITCH_JUMBO_FRAMES_ENABLED'):
161 params += ['mtu_request={}'.format(
162 S.getValue('VSWITCH_JUMBO_FRAMES_SIZE'))]
163 of_port = bridge.add_port(port_name, params)
165 return (port_name, of_port)
168 def old_dpdk_config():
169 """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
171 :returns: True if legacy --dpdk option is supported, otherwise it returns False
174 ovs_vswitchd_bin = S.getValue('TOOLS')['ovs-vswitchd']
176 subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
178 except subprocess.CalledProcessError:
181 def add_connection(self, switch_name, port1, port2, bidir=False):
182 """See IVswitch for general description
184 raise NotImplementedError()
186 def del_connection(self, switch_name, port1, port2, bidir=False):
187 """See IVswitch for general description
189 raise NotImplementedError()
191 def dump_connections(self, switch_name):
192 """See IVswitch for general description
194 raise NotImplementedError()