1 # Copyright 2015-2018 Intel Corporation., Tieto
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 """VSwitch controller for Physical to VxLAN Tunnel Endpoint to Physical
16 deployment with mod operation.
18 from netaddr import EUI, IPNetwork, mac_unix
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
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.
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
37 def __init__(self, deployment, vswitch_class, traffic):
38 """See IVswitchController for general description
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')
52 """ Sets up the switch for VxLAN overlay PTUNP (tunnel encap or decap)
54 self._logger.debug('Setting up phy-tun-phy tunneling scenario')
55 if self.tunnel_type == 'vxlan':
56 self._setup_vxlan_encap_decap()
58 self._logger.error("Only VxLAN is supported for now")
59 raise NotImplementedError
61 def _setup_vxlan_encap_decap(self):
62 """ Sets up switches for VxLAN overlay P-TUN-P test.
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.
68 self._logger.debug('Setup using %s', str(self._vswitch_class))
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=" +
77 self._vswitch.add_switch(self.bridge_mod2,
78 params=["other_config:hwaddr=" +
82 tasks.run_task(['sudo', 'iptables', '-F'],
83 self._logger, 'Clean ip tables',
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,
90 tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_mod1, 'up'],
91 self._logger, 'Bring up ' + self.bridge_mod1, False)
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,
98 tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_mod2, 'up'],
99 self._logger, 'Bring up ' + self.bridge_mod2, False)
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)
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,
119 self._vswitch.set_tunnel_arp(vxlan_local_ip2, self.br_mod_mac2,
121 self._vswitch.set_tunnel_arp(vxlan_rem_ip1, str(vxlan_rem_mac1),
123 self._vswitch.set_tunnel_arp(vxlan_rem_ip2, str(vxlan_rem_mac2),
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,
134 (_, phy4_number) = self._vswitch.add_tunnel_port(self.bridge_phy2,
138 [(_, phy5_number), (_, phy6_number)] = \
139 self._vswitch.add_veth_pair_port(self.bridge_mod1, self.bridge_mod2)
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,
148 self._vswitch.add_flow(self.bridge_phy1, flow)
149 flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy3_number,
151 self._vswitch.add_flow(self.bridge_phy1, flow)
153 flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy2_number,
155 self._vswitch.add_flow(self.bridge_phy2, flow)
156 flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy4_number,
158 self._vswitch.add_flow(self.bridge_phy2, flow)
159 flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy5_number,
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':'',
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
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,
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':'',
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]
184 flow = add_ports_to_flow(mod_flow_template, 'LOCAL', phy6_number)
185 self._vswitch.add_flow(self.bridge_mod2, flow)
192 """Tears down the switch created in setup().
194 self._logger.debug('Stop using %s', str(self._vswitch_class))
197 def get_ports_info(self):
198 """See IVswitchController for description
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)
207 def dump_vswitch_connections(self):
208 """See IVswitchController for description
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)