Merge "ci: Add SRIOV TC to CI daily job"
[vswitchperf.git] / core / vswitch_controller_ptunp.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 VxLAN Tunnel Endpoint to Physical
16    deployment with mod operation.
17 """
18
19 import logging
20 from netaddr import EUI, IPNetwork, mac_unix
21
22 from core.vswitch_controller import IVswitchController
23 from vswitches.utils import add_ports_to_flow
24 from conf import settings
25 from tools import tasks
26
27 _FLOW_TEMPLATE = {
28     'idle_timeout': '0'
29 }
30
31 class VswitchControllerPtunP(IVswitchController):
32     """VSwitch controller for VxLAN ptunp deployment scenario.
33     The deployment scenario is to test VxLAN tunneling feature without using an
34     overlay ingress traffic. The VxLAN encap and decap performed in the virtual
35     switch in each direction.
36
37     Attributes:
38         _vswitch_class: The vSwitch class to be used.
39         _vswitch: The vSwitch object controlled by this controller
40         _deployment_scenario: A string describing the scenario to set-up in the
41             constructor.
42     """
43     def __init__(self, vswitch_class, traffic):
44         """Initializes up the prerequisites for the ptunp deployment scenario.
45
46         :vswitch_class: the vSwitch class to be used.
47         """
48         self._logger = logging.getLogger(__name__)
49         self._vswitch_class = vswitch_class
50         self._vswitch = vswitch_class()
51         self._deployment_scenario = "ptunp"
52         self._traffic = traffic.copy()
53         self.bridge_phy1 = settings.getValue('TUNNEL_EXTERNAL_BRIDGE1')
54         self.bridge_phy2 = settings.getValue('TUNNEL_EXTERNAL_BRIDGE2')
55         self.bridge_mod1 = settings.getValue('TUNNEL_MODIFY_BRIDGE1')
56         self.bridge_mod2 = settings.getValue('TUNNEL_MODIFY_BRIDGE2')
57         self.br_mod_mac1 = settings.getValue('TUNNEL_MODIFY_BRIDGE_MAC1')
58         self.br_mod_mac2 = settings.getValue('TUNNEL_MODIFY_BRIDGE_MAC2')
59         self.br_mod_ip1 = settings.getValue('TUNNEL_MODIFY_BRIDGE_IP1')
60         self.br_mod_ip2 = settings.getValue('TUNNEL_MODIFY_BRIDGE_IP2')
61         self.tunnel_type = settings.getValue('TUNNEL_TYPE')
62         self._logger.debug('Creation using ' + str(self._vswitch_class))
63
64     def setup(self):
65         """ Sets up the switch for VxLAN overlay PTUNP (tunnel encap or decap)
66         """
67         self._logger.debug('Setting up phy-tun-phy tunneling scenario')
68         if self.tunnel_type is 'vxlan':
69             self._setup_vxlan_encap_decap()
70         else:
71             self._logger.error("Only VxLAN is supported for now")
72             raise NotImplementedError
73
74     def _setup_vxlan_encap_decap(self):
75         """ Sets up switches for VxLAN overlay P-TUN-P test.
76
77             Create 2 bridges br-phy1 and br-phy2 (The bridge to connect
78             physical ports. Two more bridges br-mod1 and br-mod2 to mangle
79             and redirect the packets from one tunnel port to other.
80         """
81         self._logger.debug('Setup using ' + str(self._vswitch_class))
82         try:
83             self._vswitch.start()
84             self._vswitch.add_switch(self.bridge_phy1)
85             self._vswitch.add_switch(self.bridge_phy2)
86             self._vswitch.add_switch(self.bridge_mod1,
87                                      params=["other_config:hwaddr=" +
88                                              self.br_mod_mac1
89                                             ])
90             self._vswitch.add_switch(self.bridge_mod2,
91                                      params=["other_config:hwaddr=" +
92                                              self.br_mod_mac2
93                                             ])
94
95             tasks.run_task(['sudo', 'iptables', '-F'],
96                            self._logger, 'Clean ip tables',
97                            False)
98             tasks.run_task(['sudo', 'ip', 'addr', 'add',
99                             self.br_mod_ip1, 'dev', self.bridge_mod1],
100                            self._logger, 'Assign ' +
101                            self.br_mod_ip1 + ' to ' + self.bridge_mod1,
102                            False)
103             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_mod1, 'up'],
104                            self._logger, 'Bring up ' + self.bridge_mod1, False)
105
106             tasks.run_task(['sudo', 'ip', 'addr', 'add',
107                             self.br_mod_ip2, 'dev', self.bridge_mod2],
108                            self._logger, 'Assign ' +
109                            self.br_mod_ip2 + ' to ' + self.bridge_mod2,
110                            False)
111             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_mod2, 'up'],
112                            self._logger, 'Bring up ' + self.bridge_mod2, False)
113
114             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_phy1, 'up'],
115                            self._logger, 'Bring up ' + self.bridge_phy1, False)
116             tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_phy2, 'up'],
117                            self._logger, 'Bring up ' + self.bridge_phy2, False)
118             self._vswitch.add_route(self.bridge_phy1, self.br_mod_ip1, self.bridge_mod1)
119             self._vswitch.add_route(self.bridge_phy2, self.br_mod_ip2, self.bridge_mod2)
120
121             # Create tunnel ip and mac from the bridge ips
122             vxlan_local_ip1 = str(IPNetwork(self.br_mod_ip1).ip)
123             vxlan_local_ip2 = str(IPNetwork(self.br_mod_ip2).ip)
124             vxlan_rem_ip1 = str(IPNetwork(self.br_mod_ip1).ip + 1)
125             vxlan_rem_ip2 = str(IPNetwork(self.br_mod_ip2).ip + 1)
126             vxlan_rem_mac1 = EUI(int(EUI(self.br_mod_mac1)) + 1)
127             vxlan_rem_mac1.dialect = mac_unix
128             vxlan_rem_mac2 = EUI(int(EUI(self.br_mod_mac2)) + 1)
129             vxlan_rem_mac2.dialect = mac_unix
130             self._vswitch.set_tunnel_arp(vxlan_local_ip1, self.br_mod_mac1,
131                                          self.bridge_phy1)
132             self._vswitch.set_tunnel_arp(vxlan_local_ip2, self.br_mod_mac2,
133                                          self.bridge_phy2)
134             self._vswitch.set_tunnel_arp(vxlan_rem_ip1, str(vxlan_rem_mac1),
135                                          self.bridge_mod1)
136             self._vswitch.set_tunnel_arp(vxlan_rem_ip2, str(vxlan_rem_mac2),
137                                          self.bridge_mod2)
138
139             # Lets add the ports to bridges
140             (_, phy1_number) = self._vswitch.add_phy_port(self.bridge_phy1)
141             (_, phy2_number) = self._vswitch.add_phy_port(self.bridge_phy2)
142             vxlan_vni = 'options:key=' + settings.getValue('VXLAN_VNI')
143             (_, phy3_number) = self._vswitch.add_tunnel_port(self.bridge_phy1,
144                                                              vxlan_rem_ip1,
145                                                              "vxlan",
146                                                              params=[vxlan_vni])
147             (_, phy4_number) = self._vswitch.add_tunnel_port(self.bridge_phy2,
148                                                              vxlan_rem_ip2,
149                                                              "vxlan",
150                                                              params=[vxlan_vni])
151             [(_, phy5_number), (_, phy6_number)] = \
152                      self._vswitch.add_veth_pair_port(self.bridge_mod1, self.bridge_mod2)
153
154             # Set up flows for the switches
155             self._vswitch.del_flow(self.bridge_phy1)
156             self._vswitch.del_flow(self.bridge_phy2)
157             self._vswitch.del_flow(self.bridge_mod1)
158             self._vswitch.del_flow(self.bridge_mod2)
159             flow = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number,
160                                      phy3_number)
161             self._vswitch.add_flow(self.bridge_phy1, flow)
162             flow = add_ports_to_flow(_FLOW_TEMPLATE, phy3_number,
163                                      phy1_number)
164             self._vswitch.add_flow(self.bridge_phy1, flow)
165
166             flow = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number,
167                                      phy4_number)
168             self._vswitch.add_flow(self.bridge_phy2, flow)
169             flow = add_ports_to_flow(_FLOW_TEMPLATE, phy4_number,
170                                      phy2_number)
171             self._vswitch.add_flow(self.bridge_phy2, flow)
172             flow = add_ports_to_flow(_FLOW_TEMPLATE, phy5_number,
173                                      'LOCAL')
174             self._vswitch.add_flow(self.bridge_mod1, flow)
175             mod_flow_template = _FLOW_TEMPLATE.copy()
176             mod_flow_template.update({'ip':'',
177                                       'actions':
178                                       ['mod_dl_src:' + str(vxlan_rem_mac2),
179                                        'mod_dl_dst:' + self.br_mod_mac2,
180                                        'mod_nw_src:' + vxlan_rem_ip2,
181                                        'mod_nw_dst:' + vxlan_local_ip2
182                                       ]
183                                      })
184             flow = add_ports_to_flow(mod_flow_template, 'LOCAL', phy5_number)
185             self._vswitch.add_flow(self.bridge_mod1, flow)
186             flow = add_ports_to_flow(_FLOW_TEMPLATE, phy6_number,
187                                      'LOCAL')
188             self._vswitch.add_flow(self.bridge_mod2, flow)
189             mod_flow_template = _FLOW_TEMPLATE.copy()
190             mod_flow_template.update({'ip':'',
191                                       'actions':
192                                       ['mod_dl_src:' + str(vxlan_rem_mac1),
193                                        'mod_dl_dst:' + self.br_mod_mac1,
194                                        'mod_nw_src:' + vxlan_rem_ip1,
195                                        'mod_nw_dst:' + vxlan_local_ip1]
196                                      })
197             flow = add_ports_to_flow(mod_flow_template, 'LOCAL', phy6_number)
198             self._vswitch.add_flow(self.bridge_mod2, flow)
199
200         except:
201             self._vswitch.stop()
202             raise
203
204     def stop(self):
205         """Tears down the switch created in setup().
206         """
207         self._logger.debug('Stop using ' + str(self._vswitch_class))
208         self._vswitch.stop()
209
210     def __enter__(self):
211         self.setup()
212
213     def __exit__(self, type_, value, traceback):
214         self.stop()
215
216     def get_vswitch(self):
217         """See IVswitchController for description
218         """
219         return self._vswitch
220
221     def get_ports_info(self):
222         """See IVswitchController for description
223         """
224         self._logger.debug('get_ports_info using ' + str(self._vswitch_class))
225         ports = self._vswitch.get_ports(self.bridge_phy1) +\
226                 self._vswitch.get_ports(self.bridge_mod1) +\
227                 self._vswitch.get_ports(self.bridge_phy2) +\
228                 self._vswitch.get_ports(self.bridge_mod2)
229         return ports
230
231     def dump_vswitch_flows(self):
232         """See IVswitchController for description
233         """
234         self._logger.debug('dump_flows using ' + str(self._vswitch_class))
235         self._vswitch.dump_flows(self.bridge_phy1)
236         self._vswitch.dump_flows(self.bridge_mod1)
237         self._vswitch.dump_flows(self.bridge_phy2)
238         self._vswitch.dump_flows(self.bridge_mod2)