39c8b633f1b01963f8ae1dd17223bf5fccfcc26c
[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         if settings.getValue('VNF').endswith('Cuse'):
54             self._logger.info("Inserting VHOST Cuse modules into kernel...")
55             dpdk.insert_vhost_modules()
56
57     def configure(self):
58         """ Configure vswitchd DPDK options through ovsdb if needed
59         """
60         dpdk_config = settings.getValue('VSWITCHD_DPDK_CONFIG')
61         if dpdk_config and not self.old_dpdk_config():
62             # enforce calls to ovs-vsctl with --no-wait
63             tmp_br = OFBridge(timeout=-1)
64             for option in dpdk_config:
65                 tmp_br.set_db_attribute('Open_vSwitch', '.',
66                                         'other_config:' + option, dpdk_config[option])
67
68     def start(self):
69         """See IVswitch for general description
70
71         Activates DPDK kernel modules, ovsdb and vswitchd.
72         """
73         dpdk.init()
74         super(OvsDpdkVhost, self).start()
75         # old style OVS <= 2.5.0 multi-queue enable
76         if settings.getValue('OVS_OLD_STYLE_MQ') and \
77                 int(settings.getValue('VSWITCH_MULTI_QUEUES')):
78             tmp_br = OFBridge(timeout=-1)
79             tmp_br.set_db_attribute(
80                 'Open_vSwitch', '.', 'other_config:' +
81                 'n-dpdk-rxqs', settings.getValue('VSWITCH_MULTI_QUEUES'))
82
83     def stop(self):
84         """See IVswitch for general description
85
86         Kills ovsdb and vswitchd and removes DPDK kernel modules.
87         """
88
89         super(OvsDpdkVhost, self).stop()
90         dpdk.cleanup()
91         dpdk.remove_vhost_modules()
92
93     def add_switch(self, switch_name, params=None):
94         """See IVswitch for general description
95         """
96         switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
97         if params:
98             switch_params = switch_params + params
99
100         super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
101         if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
102             # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
103             # for CPU core affinitization
104             self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.',
105                                                         'other_config:pmd-cpu-mask',
106                                                         settings.getValue('VSWITCH_PMD_CPU_MASK'))
107
108     def add_phy_port(self, switch_name):
109         """See IVswitch for general description
110
111         Creates a port of type dpdk.
112         The new port is named dpdk<n> where n is an integer starting from 0.
113         """
114         bridge = self._bridges[switch_name]
115         dpdk_count = self._get_port_count('type=dpdk')
116         port_name = 'dpdk' + str(dpdk_count)
117         params = ['--', 'set', 'Interface', port_name, 'type=dpdk']
118         # multi-queue enable
119         if int(settings.getValue('VSWITCH_MULTI_QUEUES')) and \
120                 not settings.getValue('OVS_OLD_STYLE_MQ'):
121                 params += ['options:n_rxq={}'.format(
122                     settings.getValue('VSWITCH_MULTI_QUEUES'))]
123         of_port = bridge.add_port(port_name, params)
124         return (port_name, of_port)
125
126     def add_vport(self, switch_name):
127         """See IVswitch for general description
128
129         Creates a port of type dpdkvhost
130         The new port is named dpdkvhost<n> where n is an integer starting
131         from 0
132         """
133         bridge = self._bridges[switch_name]
134         # Changed dpdkvhost to dpdkvhostuser to be able to run in Qemu 2.2
135         if settings.getValue('VNF').endswith('Cuse'):
136             vhost_count = self._get_port_count('type=dpdkvhostcuse')
137             port_name = 'dpdkvhostcuse' + str(vhost_count)
138             params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostcuse']
139         else:
140             vhost_count = self._get_port_count('type=dpdkvhostuser')
141             port_name = 'dpdkvhostuser' + str(vhost_count)
142             params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
143             # multi queue enable
144             if int(settings.getValue('VSWITCH_MULTI_QUEUES')) and \
145                     not settings.getValue('OVS_OLD_STYLE_MQ'):
146                 params += ['options:n_rxq={}'.format(
147                     settings.getValue('VSWITCH_MULTI_QUEUES'))]
148         of_port = bridge.add_port(port_name, params)
149
150         return (port_name, of_port)
151
152     @staticmethod
153     def old_dpdk_config():
154         """Checks if ovs-vswitchd uses legacy dpdk configuration via --dpdk option
155
156         :returns: True if legacy --dpdk option is supported, otherwise it returns False
157         """
158
159         ovs_vswitchd_bin = os.path.join(settings.getValue('OVS_DIR'), 'vswitchd', 'ovs-vswitchd')
160         try:
161             subprocess.check_output(ovs_vswitchd_bin + r' --help | grep "\-\-dpdk"', shell=True)
162             return True
163         except subprocess.CalledProcessError:
164             return False