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