Merge "multi-queue: Add basic multi-queue functionality"
[vswitchperf.git] / core / vswitch_controller_op2p.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 """VSwitch controller for Physical to Tunnel Endpoint to Physical deployment
16 """
17
18 import logging
19
20 from core.vswitch_controller import IVswitchController
21 from vswitches.utils import add_ports_to_flow
22 from conf import settings
23 from tools import tasks
24
25 _FLOW_TEMPLATE = {
26     'idle_timeout': '0'
27 }
28
29 class VswitchControllerOP2P(IVswitchController):
30     """VSwitch controller for OP2P deployment scenario.
31
32     Attributes:
33         _vswitch_class: The vSwitch class to be used.
34         _vswitch: The vSwitch object controlled by this controller
35         _deployment_scenario: A string describing the scenario to set-up in the
36             constructor.
37     """
38     def __init__(self, vswitch_class, traffic, tunnel_operation=None):
39         """Initializes up the prerequisites for the OP2P deployment scenario.
40
41         :vswitch_class: the vSwitch class to be used.
42         """
43         self._logger = logging.getLogger(__name__)
44         self._vswitch_class = vswitch_class
45         self._vswitch = vswitch_class()
46         self._deployment_scenario = "OP2P"
47         self._traffic = traffic.copy()
48         self._tunnel_operation = tunnel_operation
49         self._logger.debug('Creation using ' + str(self._vswitch_class))
50
51     def setup(self):
52         """ Sets up the switch for overlay P2P (tunnel encap or decap)
53         """
54         self._logger.debug('Setting up ' + str(self._tunnel_operation))
55         if self._tunnel_operation == "encapsulation":
56             self._setup_encap()
57         else:
58             if settings.getValue('VSWITCH').endswith('Vanilla'):
59                 self._setup_decap_vanilla()
60             else:
61                 self._setup_decap()
62
63     def _setup_encap(self):
64         """ Sets up the switch for overlay P2P encapsulation test
65
66         Create 2 bridges br0 (integration bridge) and br-ext and a VXLAN port
67         for encapsulation.
68         """
69         self._logger.debug('Setup using ' + str(self._vswitch_class))
70
71         try:
72             self._vswitch.start()
73             bridge = settings.getValue('TUNNEL_INTEGRATION_BRIDGE')
74             bridge_ext = settings.getValue('TUNNEL_EXTERNAL_BRIDGE')
75             bridge_ext_ip = settings.getValue('TUNNEL_EXTERNAL_BRIDGE_IP')
76             tg_port2_mac = settings.getValue('TRAFFICGEN_PORT2_MAC')
77             vtep_ip2 = settings.getValue('VTEP_IP2')
78             self._vswitch.add_switch(bridge)
79
80             tasks.run_task(['sudo', 'ip', 'addr', 'add',
81                             settings.getValue('VTEP_IP1'), 'dev', bridge],
82                            self._logger, 'Assign ' +
83                            settings.getValue('VTEP_IP1') + ' to ' + bridge,
84                            False)
85             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', bridge, 'up'],
86                            self._logger, 'Bring up ' + bridge, False)
87
88             tunnel_type = self._traffic['tunnel_type']
89
90             self._vswitch.add_switch(bridge_ext)
91             (_, phy1_number) = self._vswitch.add_phy_port(bridge)
92             (_, phy2_number) = self._vswitch.add_tunnel_port(bridge,
93                                                              vtep_ip2,
94                                                              tunnel_type)
95             self._vswitch.add_phy_port(bridge_ext)
96
97             tasks.run_task(['sudo', 'ip', 'addr', 'add',
98                             bridge_ext_ip,
99                             'dev', bridge_ext], self._logger, 'Assign ' +
100                            bridge_ext_ip + ' to ' + bridge_ext)
101
102             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', bridge_ext,
103                             'up'], self._logger,
104                            'Set ' + bridge_ext + 'status to up')
105
106             self._vswitch.add_route(bridge,
107                                     settings.getValue('VTEP_IP2_SUBNET'),
108                                     bridge_ext)
109
110             if settings.getValue('VSWITCH').endswith('Vanilla'):
111                 tasks.run_task(['sudo', 'arp', '-s', vtep_ip2, tg_port2_mac],
112                                self._logger,
113                                'Set ' + bridge_ext + ' status to up')
114             else:
115                 self._vswitch.set_tunnel_arp(vtep_ip2,
116                                              tg_port2_mac,
117                                              bridge_ext)
118
119             # Test is unidirectional for now
120             self._vswitch.del_flow(bridge)
121             flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number,
122                                       phy2_number)
123             self._vswitch.add_flow(bridge, flow1)
124
125         except:
126             self._vswitch.stop()
127             raise
128
129     def _setup_decap(self):
130         """ Sets up the switch for overlay P2P decapsulation test
131         """
132         self._logger.debug('Setup using ' + str(self._vswitch_class))
133
134         try:
135             self._vswitch.start()
136             bridge = settings.getValue('TUNNEL_INTEGRATION_BRIDGE')
137             bridge_ext = settings.getValue('TUNNEL_EXTERNAL_BRIDGE')
138             bridge_ext_ip = settings.getValue('TUNNEL_EXTERNAL_BRIDGE_IP')
139             tgen_ip1 = settings.getValue('TRAFFICGEN_PORT1_IP')
140             self._vswitch.add_switch(bridge)
141
142             tasks.run_task(['sudo', 'ip', 'addr', 'add',
143                             settings.getValue('VTEP_IP1'), 'dev', bridge],
144                            self._logger, 'Assign ' +
145                            settings.getValue('VTEP_IP1') + ' to ' + bridge, False)
146             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', bridge, 'up'],
147                            self._logger, 'Bring up ' + bridge, False)
148
149             tunnel_type = self._traffic['tunnel_type']
150
151             self._vswitch.add_switch(bridge_ext)
152             self._vswitch.add_phy_port(bridge)
153             (_, phy2_number) = self._vswitch.add_phy_port(bridge_ext)
154             if tunnel_type == "vxlan":
155                 vxlan_vni = 'options:key=' + settings.getValue('VXLAN_VNI')
156                 (_, phy3_number) = self._vswitch.add_tunnel_port(bridge_ext,
157                                                                  tgen_ip1,
158                                                                  tunnel_type,
159                                                                  params=[vxlan_vni])
160             else:
161                 (_, phy3_number) = self._vswitch.add_tunnel_port(bridge_ext,
162                                                                  tgen_ip1,
163                                                                  tunnel_type)
164             tasks.run_task(['sudo', 'ip', 'addr', 'add',
165                             bridge_ext_ip,
166                             'dev', bridge_ext],
167                            self._logger, 'Assign ' +
168                            bridge_ext_ip
169                            + ' to ' + bridge_ext)
170
171             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', bridge_ext,
172                             'up'],
173                            self._logger,
174                            'Set ' + bridge_ext + ' status to up')
175
176             self._vswitch.set_tunnel_arp(tgen_ip1,
177                                          settings.getValue('TRAFFICGEN_PORT1_MAC'),
178                                          bridge)
179             # Test is unidirectional for now
180             self._vswitch.del_flow(bridge_ext)
181             flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy3_number,
182                                       phy2_number)
183             self._vswitch.add_flow(bridge_ext, flow1)
184
185         except:
186             self._vswitch.stop()
187             raise
188
189     def _setup_decap_vanilla(self):
190         """ Sets up the switch for overlay P2P decapsulation test
191         """
192         self._logger.debug('Setup decap vanilla ' + str(self._vswitch_class))
193
194         try:
195             self._vswitch.start()
196             bridge = settings.getValue('TUNNEL_INTEGRATION_BRIDGE')
197             bridge_ext = settings.getValue('TUNNEL_EXTERNAL_BRIDGE')
198             bridge_ext_ip = settings.getValue('TUNNEL_EXTERNAL_BRIDGE_IP')
199             tgen_ip1 = settings.getValue('TRAFFICGEN_PORT1_IP')
200             self._vswitch.add_switch(bridge)
201
202             tasks.run_task(['sudo', 'ip', 'addr', 'add',
203                             settings.getValue('TUNNEL_INT_BRIDGE_IP'), 'dev', bridge],
204                            self._logger, 'Assign ' +
205                            settings.getValue('TUNNEL_INT_BRIDGE_IP') + ' to ' + bridge, False)
206             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', bridge, 'up'],
207                            self._logger, 'Bring up ' + bridge, False)
208
209             tunnel_type = self._traffic['tunnel_type']
210
211             self._vswitch.add_switch(bridge_ext)
212             self._vswitch.add_phy_port(bridge_ext)
213             (_, phy2_number) = self._vswitch.add_phy_port(bridge)
214
215             if tunnel_type == "vxlan":
216                 vxlan_vni = 'options:key=' + settings.getValue('VXLAN_VNI')
217                 self._vswitch.add_tunnel_port(bridge, tgen_ip1, tunnel_type,
218                                               params=[vxlan_vni])
219             else:
220                 self._vswitch.add_tunnel_port(bridge, tgen_ip1, tunnel_type)
221
222             tasks.run_task(['sudo', 'ip', 'addr', 'add',
223                             bridge_ext_ip,
224                             'dev', bridge_ext],
225                            self._logger, 'Assign ' +
226                            bridge_ext_ip
227                            + ' to ' + bridge_ext)
228
229             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', bridge_ext,
230                             'up'],
231                            self._logger,
232                            'Set ' + bridge_ext + ' status to up')
233
234             tg_port2_mac = settings.getValue('TRAFFICGEN_PORT2_MAC')
235             vtep_ip2 = settings.getValue('TRAFFICGEN_PORT2_IP')
236
237             self._vswitch.set_tunnel_arp(vtep_ip2,
238                                          tg_port2_mac,
239                                          bridge_ext)
240
241             self._vswitch.add_route(bridge,
242                                     settings.getValue('VTEP_IP2_SUBNET'),
243                                     bridge)
244
245
246             tasks.run_task(['sudo', 'arp', '-s', vtep_ip2, tg_port2_mac],
247                            self._logger,
248                            'Set ' + bridge_ext + ' status to up')
249
250
251             # Test is unidirectional for now
252             self._vswitch.del_flow(bridge_ext)
253
254             flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number, 'LOCAL')
255             self._vswitch.add_flow(bridge_ext, flow1)
256
257         except:
258             self._vswitch.stop()
259             raise
260
261     def stop(self):
262         """Tears down the switch created in setup().
263         """
264         self._logger.debug('Stop using ' + str(self._vswitch_class))
265         self._vswitch.stop()
266
267     def __enter__(self):
268         self.setup()
269
270     def __exit__(self, type_, value, traceback):
271         self.stop()
272
273     def get_vswitch(self):
274         """See IVswitchController for description
275         """
276         return self._vswitch
277
278     def get_ports_info(self):
279         """See IVswitchController for description
280         """
281         self._logger.debug('get_ports_info  using ' + str(self._vswitch_class))
282         return self._vswitch.get_ports(settings.getValue('VSWITCH_BRIDGE_NAME'))
283
284     def dump_vswitch_flows(self):
285         """See IVswitchController for description
286         """
287         self._vswitch.dump_flows(settings.getValue('VSWITCH_BRIDGE_NAME'))