1 # Copyright 2015-2016 Intel Corporation.
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.
20 from netaddr import EUI, IPNetwork, mac_unix
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
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.
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
43 def __init__(self, vswitch_class, traffic):
44 """Initializes up the prerequisites for the ptunp deployment scenario.
46 :vswitch_class: the vSwitch class to be used.
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))
65 """ Sets up the switch for VxLAN overlay PTUNP (tunnel encap or decap)
67 self._logger.debug('Setting up phy-tun-phy tunneling scenario')
68 if self.tunnel_type is 'vxlan':
69 self._setup_vxlan_encap_decap()
71 self._logger.error("Only VxLAN is supported for now")
72 raise NotImplementedError
74 def _setup_vxlan_encap_decap(self):
75 """ Sets up switches for VxLAN overlay P-TUN-P test.
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.
81 self._logger.debug('Setup using ' + str(self._vswitch_class))
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=" +
90 self._vswitch.add_switch(self.bridge_mod2,
91 params=["other_config:hwaddr=" +
95 tasks.run_task(['sudo', 'iptables', '-F'],
96 self._logger, 'Clean ip tables',
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,
103 tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_mod1, 'up'],
104 self._logger, 'Bring up ' + self.bridge_mod1, False)
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,
111 tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_mod2, 'up'],
112 self._logger, 'Bring up ' + self.bridge_mod2, False)
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)
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,
132 self._vswitch.set_tunnel_arp(vxlan_local_ip2, self.br_mod_mac2,
134 self._vswitch.set_tunnel_arp(vxlan_rem_ip1, str(vxlan_rem_mac1),
136 self._vswitch.set_tunnel_arp(vxlan_rem_ip2, str(vxlan_rem_mac2),
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,
147 (_, phy4_number) = self._vswitch.add_tunnel_port(self.bridge_phy2,
151 [(_, phy5_number), (_, phy6_number)] = \
152 self._vswitch.add_veth_pair_port(self.bridge_mod1, self.bridge_mod2)
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,
161 self._vswitch.add_flow(self.bridge_phy1, flow)
162 flow = add_ports_to_flow(_FLOW_TEMPLATE, phy3_number,
164 self._vswitch.add_flow(self.bridge_phy1, flow)
166 flow = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number,
168 self._vswitch.add_flow(self.bridge_phy2, flow)
169 flow = add_ports_to_flow(_FLOW_TEMPLATE, phy4_number,
171 self._vswitch.add_flow(self.bridge_phy2, flow)
172 flow = add_ports_to_flow(_FLOW_TEMPLATE, phy5_number,
174 self._vswitch.add_flow(self.bridge_mod1, flow)
175 mod_flow_template = _FLOW_TEMPLATE.copy()
176 mod_flow_template.update({'ip':'',
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
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,
188 self._vswitch.add_flow(self.bridge_mod2, flow)
189 mod_flow_template = _FLOW_TEMPLATE.copy()
190 mod_flow_template.update({'ip':'',
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]
197 flow = add_ports_to_flow(mod_flow_template, 'LOCAL', phy6_number)
198 self._vswitch.add_flow(self.bridge_mod2, flow)
205 """Tears down the switch created in setup().
207 self._logger.debug('Stop using ' + str(self._vswitch_class))
213 def __exit__(self, type_, value, traceback):
216 def get_vswitch(self):
217 """See IVswitchController for description
221 def get_ports_info(self):
222 """See IVswitchController for description
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)
231 def dump_vswitch_flows(self):
232 """See IVswitchController for description
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)