Merge "dpdk: Support of DPDK16.07"
[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
76     def stop(self):
77         """See IVswitch for general description
78
79         Kills ovsdb and vswitchd and removes DPDK kernel modules.
80         """
81         super(OvsDpdkVhost, self).stop()
82         dpdk.cleanup()
83         dpdk.remove_vhost_modules()
84
85     def add_switch(self, switch_name, params=None):
86         """See IVswitch for general description
87         """
88         switch_params = ['--', 'set', 'bridge', switch_name, 'datapath_type=netdev']
89         if params:
90             switch_params = switch_params + params
91
92         super(OvsDpdkVhost, self).add_switch(switch_name, switch_params)
93
94         if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
95             # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
96             # for CPU core affinitization
97             self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.',
98                                                         'other_config:pmd-cpu-mask',
99                                                         settings.getValue('VSWITCH_PMD_CPU_MASK'))
100
101     def add_phy_port(self, switch_name):
102         """See IVswitch for general description
103
104         Creates a port of type dpdk.
105         The new port is named dpdk<n> where n is an integer starting from 0.
106         """
107         bridge = self._bridges[switch_name]
108         dpdk_count = self._get_port_count('type=dpdk')
109         port_name = 'dpdk' + str(dpdk_count)
110         params = ['--', 'set', 'Interface', port_name, 'type=dpdk']
111         # multi-queue enable
112         if int(settings.getValue('VSWITCH_MULTI_QUEUES')):
113                 params += ['options:n_rxq={}'.format(
114                     settings.getValue('VSWITCH_MULTI_QUEUES'))]
115         of_port = bridge.add_port(port_name, params)
116         return (port_name, of_port)
117
118     def add_vport(self, switch_name):
119         """See IVswitch for general description
120
121         Creates a port of type dpdkvhost
122         The new port is named dpdkvhost<n> where n is an integer starting
123         from 0
124         """
125         bridge = self._bridges[switch_name]
126         # Changed dpdkvhost to dpdkvhostuser to be able to run in Qemu 2.2
127         if settings.getValue('VNF').endswith('Cuse'):
128             vhost_count = self._get_port_count('type=dpdkvhostcuse')
129             port_name = 'dpdkvhostcuse' + str(vhost_count)
130             params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostcuse']
131         else:
132             vhost_count = self._get_port_count('type=dpdkvhostuser')
133             port_name = 'dpdkvhostuser' + str(vhost_count)
134             params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
135             # multi queue enable
136             if int(settings.getValue('VSWITCH_MULTI_QUEUES')):
137                 params += ['options:n_rxq={}'.format(
138                     settings.getValue('VSWITCH_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