1 # Copyright 2015-2018 Intel Corporation., Tieto
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
20 from src.ovs import OFBridge
21 from src.dpdk import dpdk
22 from conf import settings as S
23 from vswitches.ovs import IVSwitchOvs
25 class OvsDpdkVhost(IVSwitchOvs):
26 """ Open vSwitch with DPDK support
28 Generic OVS wrapper functionality in src.ovs is maximally used. This
29 class wraps DPDK system configuration along with DPDK specific OVS
32 The method docstrings document only considerations specific to this
33 implementation. For generic information of the nature of the methods,
41 # legacy DPDK configuration through --dpdk option of vswitchd
42 if self.old_dpdk_config():
43 # override socket-mem settings
44 tmp_dpdk_args = S.getValue('VSWITCHD_DPDK_ARGS')
45 for tmp_arg in tmp_dpdk_args:
46 if tmp_arg.startswith('--socket-mem'):
47 tmp_dpdk_args.remove(tmp_arg)
48 tmp_dpdk_args += ['--socket-mem ' + ','.join(S.getValue('DPDK_SOCKET_MEM'))]
49 vswitchd_args = ['--dpdk'] + tmp_dpdk_args
50 # add dpdk args to generic ovs-vswitchd settings
51 if self._vswitchd_args:
52 self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args
54 self._vswitchd_args = vswitchd_args
57 """ Configure vswitchd DPDK options through ovsdb if needed
59 dpdk_config = S.getValue('VSWITCHD_DPDK_CONFIG')
60 if dpdk_config and not self.old_dpdk_config():
61 # override socket-mem settings
62 dpdk_config['dpdk-socket-mem'] = ','.join(S.getValue('DPDK_SOCKET_MEM'))
63 # enforce calls to ovs-vsctl with --no-wait
64 tmp_br = OFBridge(timeout=-1)
65 for option in dpdk_config:
66 tmp_br.set_db_attribute('Open_vSwitch', '.',
67 'other_config:' + option, dpdk_config[option])
70 """See IVswitch for general description
72 Activates DPDK kernel modules, ovsdb and vswitchd.
75 super(OvsDpdkVhost, self).start()
76 # old style OVS <= 2.5.0 multi-queue enable
77 if S.getValue('OVS_OLD_STYLE_MQ') and \
78 int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES')):
79 tmp_br = OFBridge(timeout=-1)
80 tmp_br.set_db_attribute(
81 'Open_vSwitch', '.', 'other_config:' +
82 'n-dpdk-rxqs', S.getValue('VSWITCH_DPDK_MULTI_QUEUES'))
85 """See IVswitch for general description
87 Kills ovsdb and vswitchd and removes DPDK kernel modules.
90 super(OvsDpdkVhost, self).stop()
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 S.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
102 # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
103 # for CPU core affinitization
104 self._switches[switch_name].set_db_attribute('Open_vSwitch', '.',
105 'other_config:pmd-cpu-mask',
106 S.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 _nics = S.getValue('NICS')
115 bridge = self._switches[switch_name]
116 dpdk_count = self._get_port_count('type=dpdk')
117 if dpdk_count == len(_nics):
118 raise RuntimeError("Can't add phy port! There are only {} ports defined "
119 "by WHITELIST_NICS parameter!".format(len(_nics)))
120 port_name = 'dpdk' + str(dpdk_count)
121 # PCI info. Please note there must be no blank space, eg must be
122 # like 'options:dpdk-devargs=0000:06:00.0'
123 nic_pci = 'options:dpdk-devargs=' + _nics[dpdk_count]['pci']
124 params = ['--', 'set', 'Interface', port_name, 'type=dpdk', nic_pci]
127 if int(S.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
128 not S.getValue('OVS_OLD_STYLE_MQ'):
129 params += ['options:n_rxq={}'.format(
130 S.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
131 if S.getValue('VSWITCH_JUMBO_FRAMES_ENABLED'):
132 params += ['mtu_request={}'.format(
133 S.getValue('VSWITCH_JUMBO_FRAMES_SIZE'))]
134 of_port = bridge.add_port(port_name, params)
135 return (port_name, of_port)
137 def add_vport(self, switch_name):
138 """See IVswitch for general description
140 Creates a port of type dpdkvhost
141 The new port is named dpdkvhost<n> where n is an integer starting
144 bridge = self._switches[switch_name]
146 if S.getValue('VSWITCH_VHOSTUSER_SERVER_MODE'):
147 nic_type = 'dpdkvhostuser'
149 nic_type = 'dpdkvhostuserclient'
151 vhost_count = self._get_port_count('type={}'.format(nic_type))
152 port_name = nic_type + str(vhost_count)
153 params = ['--', 'set', 'Interface', port_name, 'type={}'.format(nic_type)]
154 if not S.getValue('VSWITCH_VHOSTUSER_SERVER_MODE'):
155 params += ['--', 'set', 'Interface', port_name, 'options:vhost-server-path='
156 '{}{}'.format(S.getValue('TOOLS')['ovs_var_tmp'], port_name)]
157 if S.getValue('VSWITCH_JUMBO_FRAMES_ENABLED'):
158 params += ['mtu_request={}'.format(
159 S.getValue('VSWITCH_JUMBO_FRAMES_SIZE'))]
160 of_port = bridge.add_port(port_name, params)
162 return (port_name, of_port)
165 def old_dpdk_config():
166 """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
168 :returns: True if legacy --dpdk option is supported, otherwise it returns False
171 ovs_vswitchd_bin = S.getValue('TOOLS')['ovs-vswitchd']
173 subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
175 except subprocess.CalledProcessError: