Merge "vswitches: Affinitize vswitch threads for OVS-DPDK"
[vswitchperf.git] / vswitches / ovs_dpdk_vhost.py
1 # Copyright 2015 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 from conf import settings
20 from vswitches.vswitch import IVSwitch
21 from src.ovs import VSwitchd, OFBridge
22 from src.dpdk import dpdk
23
24 _VSWITCHD_CONST_ARGS = ['--', '--log-file']
25
26 class OvsDpdkVhost(IVSwitch):
27     """VSwitch implementation using DPDK and vhost ports
28
29     Generic OVS wrapper functionality in src.ovs is maximally used. This
30     class wraps DPDK system configuration along with DPDK specific OVS
31     parameters
32
33     The method docstrings document only considerations specific to this
34     implementation. For generic information of the nature of the methods,
35     see the interface.
36     """
37
38     _logger = logging.getLogger()
39
40     def __init__(self):
41         vswitchd_args = ['--dpdk']
42         vswitchd_args += settings.getValue('VSWITCHD_DPDK_ARGS')
43         vswitchd_args += _VSWITCHD_CONST_ARGS
44
45         self._logger.info("Inserting VHOST modules into kernel...")
46         dpdk.insert_vhost_modules()
47
48         self._vswitchd = VSwitchd(vswitchd_args=vswitchd_args,
49                                   expected_cmd=
50                                   r'EAL: Master l*core \d+ is ready')
51         self._bridges = {}
52
53     def start(self):
54         """See IVswitch for general description
55
56         Activates DPDK kernel modules, ovsdb and vswitchd.
57         """
58         dpdk.init()
59         self._vswitchd.start()
60
61     def stop(self):
62         """See IVswitch for general description
63
64         Kills ovsdb and vswitchd and removes DPDK kernel modules.
65         """
66         self._vswitchd.kill()
67         dpdk.cleanup()
68         dpdk.remove_vhost_modules()
69
70     def add_switch(self, switch_name):
71         """See IVswitch for general description
72         """
73         bridge = OFBridge(switch_name)
74         bridge.create()
75         bridge.set_db_attribute('Open_vSwitch', '.',
76                                 'other_config:max-idle',
77                                 settings.getValue('VSWITCH_FLOW_TIMEOUT'))
78
79         if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
80             # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
81             # for CPU core affinitization
82             bridge.set_db_attribute('Open_vSwitch', '.',
83                                     'other_config:pmd-cpu-mask',
84                                     settings.getValue('VSWITCH_PMD_CPU_MASK'))
85
86         bridge.set_db_attribute('Bridge', bridge.br_name,
87                                 'datapath_type', 'netdev')
88         self._bridges[switch_name] = bridge
89
90     def del_switch(self, switch_name):
91         """See IVswitch for general description
92         """
93         bridge = self._bridges[switch_name]
94         self._bridges.pop(switch_name)
95         bridge.destroy()
96
97     def add_phy_port(self, switch_name):
98         """See IVswitch for general description
99
100         Creates a port of type dpdk.
101         The new port is named dpdk<n> where n is an integer starting from 0.
102         """
103         bridge = self._bridges[switch_name]
104         dpdk_count = self._get_port_count(bridge, 'type=dpdk')
105         port_name = 'dpdk' + str(dpdk_count)
106         params = ['--', 'set', 'Interface', port_name, 'type=dpdk']
107         of_port = bridge.add_port(port_name, params)
108
109         return (port_name, of_port)
110
111     def add_vport(self, switch_name):
112         """See IVswitch for general description
113
114         Creates a port of type dpdkvhost
115         The new port is named dpdkvhost<n> where n is an integer starting
116         from 0
117         """
118         bridge = self._bridges[switch_name]
119         # Changed dpdkvhost to dpdkvhostuser to be able to run in Qemu 2.2
120         vhost_method = settings.getValue('VHOST_METHOD')
121         if vhost_method == "cuse":
122             vhost_count = self._get_port_count(bridge, 'type=dpdkvhostcuse')
123             port_name = 'dpdkvhostcuse' + str(vhost_count)
124             params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostcuse']
125         else:
126             vhost_count = self._get_port_count(bridge, 'type=dpdkvhostuser')
127             port_name = 'dpdkvhostuser' + str(vhost_count)
128             params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
129
130         of_port = bridge.add_port(port_name, params)
131
132         return (port_name, of_port)
133
134     def get_ports(self, switch_name):
135         """See IVswitch for general description
136         """
137         bridge = self._bridges[switch_name]
138         ports = list(bridge.get_ports().items())
139         return [(name, of_port) for (name, (of_port, _)) in ports]
140
141     def del_port(self, switch_name, port_name):
142         """See IVswitch for general description
143         """
144         bridge = self._bridges[switch_name]
145         bridge.del_port(port_name)
146
147     def add_flow(self, switch_name, flow):
148         """See IVswitch for general description
149         """
150         bridge = self._bridges[switch_name]
151         bridge.add_flow(flow)
152
153     def del_flow(self, switch_name, flow=None):
154         """See IVswitch for general description
155         """
156         flow = flow or {}
157         bridge = self._bridges[switch_name]
158         bridge.del_flow(flow)
159
160     @staticmethod
161     def _get_port_count(bridge, param):
162         """Returns the number of ports having a certain parameter
163
164         :param bridge: The src.ovs.ofctl.OFBridge on which to operate
165         :param param: The parameter to search for
166         :returns: Count of matches
167         """
168         port_params = [c for (_, (_, c)) in list(bridge.get_ports().items())]
169         param_hits = [i for i in port_params if param in i]
170         return len(param_hits)