Merge "multi-queue: Add basic multi-queue functionality"
[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         self._expect = r'EAL: Master l*core \d+ is ready'
43
44         vswitchd_args = []
45
46         # legacy DPDK configuration through --dpdk option of vswitchd
47         if self.old_dpdk_config():
48             vswitchd_args = ['--dpdk'] + settings.getValue('VSWITCHD_DPDK_ARGS')
49             if self._vswitchd_args:
50                 self._vswitchd_args = vswitchd_args + ['--'] + self._vswitchd_args
51             else:
52                 self._vswitchd_args = vswitchd_args
53
54         if settings.getValue('VNF').endswith('Cuse'):
55             self._logger.info("Inserting VHOST Cuse modules into kernel...")
56             dpdk.insert_vhost_modules()
57
58     def configure(self):
59         """ Configure vswitchd DPDK options through ovsdb if needed
60         """
61         dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG')
62         if dpdk_config and not self.old_dpdk_config():
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])
68
69     def start(self):
70         """See IVswitch for general description
71
72         Activates DPDK kernel modules, ovsdb and vswitchd.
73         """
74         dpdk.init()
75         super(OvsDpdkVhost, self).start()
76
77     def stop(self):
78         """See IVswitch for general description
79
80         Kills ovsdb and vswitchd and removes DPDK kernel modules.
81         """
82         super(OvsDpdkVhost, self).stop()
83         dpdk.cleanup()
84         dpdk.remove_vhost_modules()
85
86     def add_switch(self, switch_name, params=None):
87         """See IVswitch for general description
88         """
89         switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
90         if params:
91             switch_params = switch_params + params
92
93         super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
94
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'))
101
102     def add_phy_port(self, switch_name):
103         """See IVswitch for general description
104
105         Creates a port of type dpdk.
106         The new port is named dpdk<n> where n is an integer starting from 0.
107         """
108         bridge = self._bridges[switch_name]
109         dpdk_count = self._get_port_count('type=dpdk')
110         port_name = 'dpdk' + str(dpdk_count)
111         params = ['--', 'set', 'Interface', port_name, 'type=dpdk']
112         # multi-queue enable
113         if int(settings.getValue('VSWITCH_MULTI_QUEUES')):
114                 params += ['options:n_rxq={}'.format(
115                     settings.getValue('VSWITCH_MULTI_QUEUES'))]
116         of_port = bridge.add_port(port_name, params)
117         return (port_name, of_port)
118
119     def add_vport(self, switch_name):
120         """See IVswitch for general description
121
122         Creates a port of type dpdkvhost
123         The new port is named dpdkvhost<n> where n is an integer starting
124         from 0
125         """
126         bridge = self._bridges[switch_name]
127         # Changed dpdkvhost to dpdkvhostuser to be able to run in Qemu 2.2
128         if settings.getValue('VNF').endswith('Cuse'):
129             vhost_count = self._get_port_count('type=dpdkvhostcuse')
130             port_name = 'dpdkvhostcuse' + str(vhost_count)
131             params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostcuse']
132         else:
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             # multi queue enable
137             if int(settings.getValue('VSWITCH_MULTI_QUEUES')):
138                 params += ['options:n_rxq={}'.format(
139                     settings.getValue('VSWITCH_MULTI_QUEUES'))]
140         of_port = bridge.add_port(port_name, params)
141
142         return (port_name, of_port)
143
144     @staticmethod
145     def old_dpdk_config():
146         """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
147
148         :returns: True if legacy --dpdk option is supported, otherwise it returns False
149         """
150
151         ovs_vswitchd_bin = os.path.join(settings.getValue('OVS_DIR'), 'vswitchd', 'ovs-vswitchd')
152         try:
153             subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
154             return True
155         except subprocess.CalledProcessError:
156             return False