trafficgen: pause trafficgenerator
[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', params=None):
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         local_params = ['--', 'set', 'Interface', port_name,
145                         'type=' + tunnel_type,
146                         'options:remote_ip=' + remote_ip]
147
148         if params is not None:
149             local_params = local_params + params
150
151         of_port = bridge.add_port(port_name, local_params)
152         return (port_name, of_port)
153
154     def get_ports(self, switch_name):
155         """See IVswitch for general description
156         """
157         bridge = self._bridges[switch_name]
158         ports = list(bridge.get_ports().items())
159         return [(name, of_port) for (name, (of_port, _)) in ports]
160
161     def del_port(self, switch_name, port_name):
162         """See IVswitch for general description
163         """
164         bridge = self._bridges[switch_name]
165         bridge.del_port(port_name)
166
167     def add_flow(self, switch_name, flow, cache='off'):
168         """See IVswitch for general description
169         """
170         bridge = self._bridges[switch_name]
171         bridge.add_flow(flow, cache=cache)
172
173     def del_flow(self, switch_name, flow=None):
174         """See IVswitch for general description
175         """
176         flow = flow or {}
177         bridge = self._bridges[switch_name]
178         bridge.del_flow(flow)
179
180     def dump_flows(self, switch_name):
181         """See IVswitch for general description
182         """
183         bridge = self._bridges[switch_name]
184         bridge.dump_flows()
185
186     def add_route(self, switch_name, network, destination):
187         """See IVswitch for general description
188         """
189         bridge = self._bridges[switch_name]
190         bridge.add_route(network, destination)
191
192     def set_tunnel_arp(self, ip_addr, mac_addr, switch_name):
193         """See IVswitch for general description
194         """
195         bridge = self._bridges[switch_name]
196         bridge.set_tunnel_arp(ip_addr, mac_addr, switch_name)
197
198     def _get_port_count(self, param):
199         """Returns the number of ports having a certain parameter
200
201         :param bridge: The src.ovs.ofctl.OFBridge on which to operate
202         :param param: The parameter to search for
203         :returns: Count of matches
204         """
205         cnt = 0
206         for k in self._bridges:
207             pparams = [c for (_, (_, c)) in list(self._bridges[k].get_ports().items())]
208             phits = [i for i in pparams if param in i]
209             cnt += len(phits)
210
211         if cnt is None:
212             cnt = 0
213         return cnt