Add OVS tunnel encapsulation performance test
[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 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 = ['--', '--pidfile', '--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         if settings.getValue('VNF').endswith('Cuse'):
46             self._logger.info("Inserting VHOST Cuse modules into kernel...")
47             dpdk.insert_vhost_modules()
48
49         self._vswitchd = VSwitchd(vswitchd_args=vswitchd_args,
50                                   expected_cmd=
51                                   r'EAL: Master l*core \d+ is ready')
52         self._bridges = {}
53
54     def start(self):
55         """See IVswitch for general description
56
57         Activates DPDK kernel modules, ovsdb and vswitchd.
58         """
59         dpdk.init()
60         self._vswitchd.start()
61
62     def stop(self):
63         """See IVswitch for general description
64
65         Kills ovsdb and vswitchd and removes DPDK kernel modules.
66         """
67         self._vswitchd.kill()
68         dpdk.cleanup()
69         dpdk.remove_vhost_modules()
70
71     def add_switch(self, switch_name, params=None):
72         """See IVswitch for general description
73         """
74         bridge = OFBridge(switch_name)
75         if params is None:
76             bridge.create(['--', 'set', 'bridge', switch_name,
77                            'datapath_type=netdev'])
78         else:
79             bridge.create(['--', 'set', 'bridge', switch_name,
80                            'datapath_type=netdev'] + params)
81
82         bridge.set_db_attribute('Open_vSwitch', '.',
83                                 'other_config:max-idle',
84                                 settings.getValue('VSWITCH_FLOW_TIMEOUT'))
85
86         if settings.getValue('VSWITCH_AFFINITIZATION_ON') == 1:
87             # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK
88             # for CPU core affinitization
89             bridge.set_db_attribute('Open_vSwitch', '.',
90                                     'other_config:pmd-cpu-mask',
91                                     settings.getValue('VSWITCH_PMD_CPU_MASK'))
92
93         self._bridges[switch_name] = bridge
94
95     def del_switch(self, switch_name):
96         """See IVswitch for general description
97         """
98         bridge = self._bridges[switch_name]
99         self._bridges.pop(switch_name)
100         bridge.destroy()
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         of_port = bridge.add_port(port_name, params)
113
114         return (port_name, of_port)
115
116     def add_vport(self, switch_name):
117         """See IVswitch for general description
118
119         Creates a port of type dpdkvhost
120         The new port is named dpdkvhost<n> where n is an integer starting
121         from 0
122         """
123         bridge = self._bridges[switch_name]
124         # Changed dpdkvhost to dpdkvhostuser to be able to run in Qemu 2.2
125         if settings.getValue('VNF').endswith('Cuse'):
126             vhost_count = self._get_port_count('type=dpdkvhostcuse')
127             port_name = 'dpdkvhostcuse' + str(vhost_count)
128             params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostcuse']
129         else:
130             vhost_count = self._get_port_count('type=dpdkvhostuser')
131             port_name = 'dpdkvhostuser' + str(vhost_count)
132             params = ['--', 'set', 'Interface', port_name, 'type=dpdkvhostuser']
133
134         of_port = bridge.add_port(port_name, params)
135
136         return (port_name, of_port)
137
138     def add_tunnel_port(self, switch_name, remote_ip, tunnel_type='vxlan'):
139         """Creates tunneling port
140         """
141         bridge = self._bridges[switch_name]
142         pcount = str(self._get_port_count('type=' + tunnel_type))
143         port_name = tunnel_type + pcount
144         params = ['--', 'set', 'Interface', port_name, 'type=' + tunnel_type,
145                   'options:remote_ip=' + remote_ip]
146         of_port = bridge.add_port(port_name, params)
147         return (port_name, of_port)
148
149     def get_ports(self, switch_name):
150         """See IVswitch for general description
151         """
152         bridge = self._bridges[switch_name]
153         ports = list(bridge.get_ports().items())
154         return [(name, of_port) for (name, (of_port, _)) in ports]
155
156     def del_port(self, switch_name, port_name):
157         """See IVswitch for general description
158         """
159         bridge = self._bridges[switch_name]
160         bridge.del_port(port_name)
161
162     def add_flow(self, switch_name, flow, cache='off'):
163         """See IVswitch for general description
164         """
165         bridge = self._bridges[switch_name]
166         bridge.add_flow(flow, cache=cache)
167
168     def del_flow(self, switch_name, flow=None):
169         """See IVswitch for general description
170         """
171         flow = flow or {}
172         bridge = self._bridges[switch_name]
173         bridge.del_flow(flow)
174
175     def dump_flows(self, switch_name):
176         """See IVswitch for general description
177         """
178         bridge = self._bridges[switch_name]
179         bridge.dump_flows()
180
181     def add_route(self, switch_name, network, destination):
182         """See IVswitch for general description
183         """
184         bridge = self._bridges[switch_name]
185         bridge.add_route(network, destination)
186
187     def set_tunnel_arp(self, ip_addr, mac_addr, switch_name):
188         """See IVswitch for general description
189         """
190         bridge = self._bridges[switch_name]
191         bridge.set_tunnel_arp(ip_addr, mac_addr, switch_name)
192
193     def _get_port_count(self, param):
194         """Returns the number of ports having a certain parameter
195
196         :param bridge: The src.ovs.ofctl.OFBridge on which to operate
197         :param param: The parameter to search for
198         :returns: Count of matches
199         """
200         cnt = 0
201         for k in self._bridges:
202             pparams = [c for (_, (_, c)) in list(self._bridges[k].get_ports().items())]
203             phits = [i for i in pparams if param in i]
204             cnt += len(phits)
205
206         if cnt is None:
207             cnt = 0
208         return cnt