0d34ce3e41adfab0028d9a5365ea8231d9d633bf
[csit.git] / resources / libraries / python / L2Util.py
1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """L2 Utilities Library."""
15
16 from robot.api.deco import keyword
17 from resources.libraries.python.topology import Topology
18 from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal
19 from resources.libraries.python.ssh import exec_cmd_no_error
20
21 class L2Util(object):
22     """Utilities for l2 configuration"""
23
24     @staticmethod
25     def vpp_add_l2fib_entry(node, mac, interface, bd_id):
26         """ Create a static L2FIB entry on a vpp node.
27
28         :param node: Node to add L2FIB entry on.
29         :param mac: Destination mac address.
30         :param interface: Interface name or sw_if_index.
31         :param bd_id: Bridge domain id.
32         :type node: dict
33         :type mac: str
34         :type interface: str or int
35         :type bd_id: int
36         """
37         if isinstance(interface, basestring):
38             sw_if_index = Topology.get_interface_sw_index(node, interface)
39         else:
40             sw_if_index = interface
41         VatExecutor.cmd_from_template(node, "add_l2_fib_entry.vat",
42                                       mac=mac, bd=bd_id,
43                                       interface=sw_if_index)
44
45     @staticmethod
46     def create_l2_bd(node, bd_id, flood=1, uu_flood=1, forward=1, learn=1,
47                      arp_term=0):
48         """Create a l2 bridge domain on the chosen VPP node
49
50         Execute "bridge_domain_add_del bd_id {bd_id} flood {flood} uu-flood 1
51         forward {forward} learn {learn} arp-term {arp_term}" VAT command on
52         the node.
53
54         :param node: node where we wish to crate the l2 bridge domain
55         :param bd_id: bridge domain index number
56         :param flood: enable flooding
57         :param uu_flood: enable uu_flood
58         :param forward: enable forwarding
59         :param learn: enable mac address learning to fib
60         :param arp_term: enable arp_termination
61         :type node: dict
62         :type bd_id: int
63         :type flood: bool
64         :type uu_flood: bool
65         :type forward: bool
66         :type learn: bool
67         :type arp_term:bool
68         """
69         VatExecutor.cmd_from_template(node, "l2_bd_create.vat",
70                                       bd_id=bd_id, flood=flood,
71                                       uu_flood=uu_flood, forward=forward,
72                                       learn=learn, arp_term=arp_term)
73
74     @staticmethod
75     def add_interface_to_l2_bd(node, interface, bd_id, shg=0):
76         """Add a interface to the l2 bridge domain.
77
78         Get SW IF ID and add it to the bridge domain.
79
80         :param node: node where we want to execute the command that does this
81         :param interface: interface name
82         :param bd_id: bridge domain index number to add Interface name to
83         :param shg: split horizon group
84         :type node: dict
85         :type interface: str
86         :type bd_id: int
87         :type shg: int
88         """
89         sw_if_index = Topology.get_interface_sw_index(node, interface)
90         L2Util.add_sw_if_index_to_l2_bd(node, sw_if_index, bd_id, shg)
91
92     @staticmethod
93     def add_sw_if_index_to_l2_bd(node, sw_if_index, bd_id, shg=0):
94         """Add interface with sw_if_index to l2 bridge domain.
95
96         Execute the "sw_interface_set_l2_bridge sw_if_index {sw_if_index}
97         bd_id {bd_id} shg {shg} enable" VAT command on the given node.
98
99         :param node: node where we want to execute the command that does this
100         :param sw_if_index: interface index
101         :param bd_id: bridge domain index number to add SW IF ID to
102         :param shg: split horizon group
103         :type node: dict
104         :type sw_if_index: int
105         :type bd_id: int
106         :type shg: int
107         :return:
108         """
109         VatExecutor.cmd_from_template(node, "l2_bd_add_sw_if_index.vat",
110                                       bd_id=bd_id, sw_if_index=sw_if_index,
111                                       shg=shg)
112
113     @staticmethod
114     @keyword('Create dict used in bridge domain template file for node '
115              '"${node}" with links "${link_names}" and bd_id "${bd_id}"')
116     def create_bridge_domain_vat_dict(node, link_names, bd_id):
117         """Create dictionary that can be used in l2 bridge domain template.
118
119         :param node: node data dictionary
120         :param link_names: list of names of links the bridge domain should be
121         connecting
122         :param bd_id: bridge domain index number
123         :type node: dict
124         :type link_names: list
125         :return: dictionary used to generate l2 bridge domain VAT configuration
126         from template file
127         The resulting dictionary looks like this:
128         'interface1': interface name of first interface
129         'interface2': interface name of second interface
130         'bd_id': bridge domain index
131         """
132         bd_dict = Topology().get_interfaces_by_link_names(node, link_names)
133         bd_dict['bd_id'] = bd_id
134         return bd_dict
135
136     @staticmethod
137     def vpp_add_l2_bridge_domain(node, bd_id, port_1, port_2, learn=True):
138         """Add L2 bridge domain with 2 interfaces to the VPP node.
139
140         :param node: Node to add L2BD on.
141         :param bd_id: Bridge domain ID.
142         :param port_1: First interface name added to L2BD.
143         :param port_2: Second interface name added to L2BD.
144         :param learn: Enable/disable MAC learn.
145         :type node: dict
146         :type bd_id: int
147         :type port_1: str
148         :type port_2: str
149         :type learn: bool
150         """
151         sw_if_index1 = Topology.get_interface_sw_index(node, port_1)
152         sw_if_index2 = Topology.get_interface_sw_index(node, port_2)
153         VatExecutor.cmd_from_template(node,
154                                       'l2_bridge_domain.vat',
155                                       sw_if_id1=sw_if_index1,
156                                       sw_if_id2=sw_if_index2,
157                                       bd_id=bd_id,
158                                       learn=int(learn))
159
160     @staticmethod
161     def vpp_setup_bidirectional_cross_connect(node, interface1, interface2):
162         """Create bidirectional cross-connect between 2 interfaces on vpp node.
163
164         :param node: Node to add bidirectional cross-connect
165         :param interface1: first interface name or sw_if_index
166         :param interface2: second interface name or sw_if_index
167         :type node: dict
168         :type interface1: str or int
169         :type interface2: str or int
170         """
171
172         if isinstance(interface1, basestring):
173             sw_iface1 = Topology().get_interface_sw_index(node, interface1)
174         else:
175             sw_iface1 = interface1
176
177         if isinstance(interface2, basestring):
178             sw_iface2 = Topology().get_interface_sw_index(node, interface2)
179         else:
180             sw_iface2 = interface2
181
182         with VatTerminal(node) as vat:
183             vat.vat_terminal_exec_cmd_from_template('l2_xconnect.vat',
184                                                     interface1=sw_iface1,
185                                                     interface2=sw_iface2)
186             vat.vat_terminal_exec_cmd_from_template('l2_xconnect.vat',
187                                                     interface1=sw_iface2,
188                                                     interface2=sw_iface1)
189
190     @staticmethod
191     def linux_add_bridge(node, br_name, if_1, if_2):
192         """Bridge two interfaces on linux node.
193
194         :param node: Node to add bridge on.
195         :param br_name: Bridge name.
196         :param if_1: First interface to be added to the bridge.
197         :param if_2: Second interface to be added to the bridge.
198         :type node: dict
199         :type br_name: str
200         :type if_1: str
201         :type if_2: str
202         """
203         cmd = 'brctl addbr {0}'.format(br_name)
204         exec_cmd_no_error(node, cmd, sudo=True)
205         cmd = 'brctl addif {0} {1}'.format(br_name, if_1)
206         exec_cmd_no_error(node, cmd, sudo=True)
207         cmd = 'brctl addif {0} {1}'.format(br_name, if_2)
208         exec_cmd_no_error(node, cmd, sudo=True)
209
210     @staticmethod
211     def linux_del_bridge(node, br_name):
212         """Delete bridge from linux node.
213
214         :param node: Node to delete bridge from.
215         :param br_name: Bridge name.
216         .. note:: The network interface corresponding to the bridge must be
217         down before it can be deleted!
218         """
219         cmd = 'brctl delbr {0}'.format(br_name)
220         exec_cmd_no_error(node, cmd, sudo=True)