c0764c87ecb27ce422fb2dca4e68cae2e9f604c1
[vswitchperf.git] / vswitches / ovs_dpdk_vhost.py
1 # Copyright 2015-2016 Intel Corporation.
2 #
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
6 #
7 #   http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 """VSPERF VSwitch implementation using DPDK and vhost ports
16 """
17
18 import logging
19 import subprocess
20 import os
21
22 from src.ovs import OFBridge
23 from src.dpdk import dpdk
24 from conf import settings
25 from vswitches.ovs import IVSwitchOvs
26
27 class OvsDpdkVhost(IVSwitchOvs):
28     """ Open vSwitch with DPDK support
29
30     Generic OVS wrapper functionality in src.ovs is maximally used. This
31     class wraps DPDK system configuration along with DPDK specific OVS
32     parameters
33
34     The method docstrings document only considerations specific to this
35     implementation. For generic information of the nature of the methods,
36     see the interface.
37     """
38
39     def __init__(self):
40         super(OvsDpdkVhost, self).__init__()
41         self._logger = logging.getLogger(__name__)
42
43         vswitchd_args = []
44
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
50             else:
51                 self._vswitchd_args = vswitchd_args
52
53     def configure(self):
54         """ Configure vswitchd DPDK options through ovsdb if needed
55         """
56         dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG')
57         if dpdk_config and not self.old_dpdk_config():
58             # enforce calls to ovs-vsctl with --no-wait
59             tmp_br = OFBridge(timeout=-1)
60             for option in dpdk_config:
61                 tmp_br.set_db_attribute('Open_vSwitch', '.',
62                                         'other_config:' + option, dpdk_config[option])
63
64     def start(self):
65         """See IVswitch for general description
66
67         Activates DPDK kernel modules, ovsdb and vswitchd.
68         """
69         dpdk.init()
70         super(OvsDpdkVhost, self).start()
71         # old style OVS <= 2.5.0 multi-queue enable
72         if settings.getValue('OVS_OLD_STYLE_MQ') and \
73                 int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')):
74             tmp_br = OFBridge(timeout=-1)
75             tmp_br.set_db_attribute(
76                 'Open_vSwitch', '.', 'other_config:' +
77                 'n-dpdk-rxqs', settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))
78
79     def stop(self):
80         """See IVswitch for general description
81
82         Kills ovsdb and vswitchd and removes DPDK kernel modules.
83         """
84
85         super(OvsDpdkVhost, self).stop()
86         dpdk.cleanup()
87         dpdk.remove_vhost_modules()
88
89     def add_switch(self, switch_name, params=None):
90         """See IVswitch for general description
91         """
92         switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
93         if params:
94             switch_params = switch_params + params
95
96         super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
97         if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
98             # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
99             # for CPU core affinitization
100             self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.',
101                                                         'other_config:pmd-cpu-mask',
102                                                         settings.getValue('VSWITCH_PMD_CPU_MASK'))
103
104     def add_phy_port(self, switch_name):
105         """See IVswitch for general description
106
107         Creates a port of type dpdk.
108         The new port is named dpdk<n> where n is an integer starting from 0.
109         """
110         bridge = self._bridges[switch_name]
111         dpdk_count = self._get_port_count('type=dpdk')
112         port_name = 'dpdk' + str(dpdk_count)
113         params = ['--', 'set', 'Interface', port_name, 'type=dpdk']
114         # multi-queue enable
115
116         if int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
117                 not settings.getValue('OVS_OLD_STYLE_MQ'):
118                 params += ['options:n_rxq={}'.format(
119                     settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
120         of_port = bridge.add_port(port_name, params)
121         return (port_name, of_port)
122
123     def add_vport(self, switch_name):
124         """See IVswitch for general description
125
126         Creates a port of type dpdkvhost
127         The new port is named dpdkvhost<n> where n is an integer starting
128         from 0
129         """
130         bridge = self._bridges[switch_name]
131         vhost_count = self._get_port_count('type=dpdkvhostuser')
132         port_name = 'dpdkvhostuser' + str(vhost_count)
133         params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
134         # multi queue enable
135         if int(settings.getValue('VSWITCH_DPDK_MULTI_QUEUES')) and \
136                 not settings.getValue('OVS_OLD_STYLE_MQ'):
137             params += ['options:n_rxq={}'.format(
138                 settings.getValue('VSWITCH_DPDK_MULTI_QUEUES'))]
139         of_port = bridge.add_port(port_name, params)
140
141         return (port_name, of_port)
142
143     @staticmethod
144     def old_dpdk_config():
145         """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
146
147         :returns: True if legacy --dpdk option is supported, otherwise it returns False
148         """
149
150         ovs_vswitchd_bin = os.path.join(settings.getValue('OVS_DIR'), 'vswitchd', 'ovs-vswitchd')
151         try:
152             subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
153             return True
154         except subprocess.CalledProcessError:
155             return False