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:
6 # http://www.apache.org/licenses/LICENSE-2.0
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.
14 """L2 Utilities Library."""
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
23 """Utilities for l2 configuration"""
26 def vpp_add_l2fib_entry(node, mac, interface, bd_id):
27 """ Create a static L2FIB entry on a vpp node.
29 :param node: Node to add L2FIB entry on.
30 :param mac: Destination mac address.
31 :param interface: Interface name or sw_if_index.
32 :param bd_id: Bridge domain id.
35 :type interface: str or int
38 if isinstance(interface, basestring):
39 sw_if_index = Topology.get_interface_sw_index(node, interface)
41 sw_if_index = interface
42 VatExecutor.cmd_from_template(node, "add_l2_fib_entry.vat",
44 interface=sw_if_index)
47 def create_l2_bd(node, bd_id, flood=1, uu_flood=1, forward=1, learn=1,
49 """Create a l2 bridge domain on the chosen VPP node
51 Execute "bridge_domain_add_del bd_id {bd_id} flood {flood} uu-flood 1
52 forward {forward} learn {learn} arp-term {arp_term}" VAT command on
55 :param node: node where we wish to crate the l2 bridge domain
56 :param bd_id: bridge domain index number
57 :param flood: enable flooding
58 :param uu_flood: enable uu_flood
59 :param forward: enable forwarding
60 :param learn: enable mac address learning to fib
61 :param arp_term: enable arp_termination
70 VatExecutor.cmd_from_template(node, "l2_bd_create.vat",
71 bd_id=bd_id, flood=flood,
72 uu_flood=uu_flood, forward=forward,
73 learn=learn, arp_term=arp_term)
76 def add_interface_to_l2_bd(node, interface, bd_id, shg=0):
77 """Add a interface to the l2 bridge domain.
79 Get SW IF ID and add it to the bridge domain.
81 :param node: node where we want to execute the command that does this
82 :param interface: interface name
83 :param bd_id: bridge domain index number to add Interface name to
84 :param shg: split horizon group
90 sw_if_index = Topology.get_interface_sw_index(node, interface)
91 L2Util.add_sw_if_index_to_l2_bd(node, sw_if_index, bd_id, shg)
94 def add_sw_if_index_to_l2_bd(node, sw_if_index, bd_id, shg=0):
95 """Add interface with sw_if_index to l2 bridge domain.
97 Execute the "sw_interface_set_l2_bridge sw_if_index {sw_if_index}
98 bd_id {bd_id} shg {shg} enable" VAT command on the given node.
100 :param node: node where we want to execute the command that does this
101 :param sw_if_index: interface index
102 :param bd_id: bridge domain index number to add SW IF ID to
103 :param shg: split horizon group
105 :type sw_if_index: int
110 VatExecutor.cmd_from_template(node, "l2_bd_add_sw_if_index.vat",
111 bd_id=bd_id, sw_if_index=sw_if_index,
115 @keyword('Create dict used in bridge domain template file for node '
116 '"${node}" with links "${link_names}" and bd_id "${bd_id}"')
117 def create_bridge_domain_vat_dict(node, link_names, bd_id):
118 """Create dictionary that can be used in l2 bridge domain template.
120 :param node: node data dictionary
121 :param link_names: list of names of links the bridge domain should be
123 :param bd_id: bridge domain index number
125 :type link_names: list
126 :return: dictionary used to generate l2 bridge domain VAT configuration
128 The resulting dictionary looks like this:
129 'interface1': interface name of first interface
130 'interface2': interface name of second interface
131 'bd_id': bridge domain index
133 bd_dict = Topology().get_interfaces_by_link_names(node, link_names)
134 bd_dict['bd_id'] = bd_id
138 def vpp_add_l2_bridge_domain(node, bd_id, port_1, port_2, learn=True):
139 """Add L2 bridge domain with 2 interfaces to the VPP node.
141 :param node: Node to add L2BD on.
142 :param bd_id: Bridge domain ID.
143 :param port_1: First interface name added to L2BD.
144 :param port_2: Second interface name added to L2BD.
145 :param learn: Enable/disable MAC learn.
152 sw_if_index1 = Topology.get_interface_sw_index(node, port_1)
153 sw_if_index2 = Topology.get_interface_sw_index(node, port_2)
154 VatExecutor.cmd_from_template(node,
155 'l2_bridge_domain.vat',
156 sw_if_id1=sw_if_index1,
157 sw_if_id2=sw_if_index2,
162 def vpp_setup_bidirectional_cross_connect(node, interface1, interface2):
163 """Create bidirectional cross-connect between 2 interfaces on vpp node.
165 :param node: Node to add bidirectional cross-connect
166 :param interface1: first interface name or sw_if_index
167 :param interface2: second interface name or sw_if_index
169 :type interface1: str or int
170 :type interface2: str or int
173 if isinstance(interface1, basestring):
174 sw_iface1 = Topology().get_interface_sw_index(node, interface1)
176 sw_iface1 = interface1
178 if isinstance(interface2, basestring):
179 sw_iface2 = Topology().get_interface_sw_index(node, interface2)
181 sw_iface2 = interface2
183 with VatTerminal(node) as vat:
184 vat.vat_terminal_exec_cmd_from_template('l2_xconnect.vat',
185 interface1=sw_iface1,
186 interface2=sw_iface2)
187 vat.vat_terminal_exec_cmd_from_template('l2_xconnect.vat',
188 interface1=sw_iface2,
189 interface2=sw_iface1)
192 def linux_add_bridge(node, br_name, if_1, if_2):
193 """Bridge two interfaces on linux node.
195 :param node: Node to add bridge on.
196 :param br_name: Bridge name.
197 :param if_1: First interface to be added to the bridge.
198 :param if_2: Second interface to be added to the bridge.
204 cmd = 'brctl addbr {0}'.format(br_name)
205 exec_cmd_no_error(node, cmd, sudo=True)
206 cmd = 'brctl addif {0} {1}'.format(br_name, if_1)
207 exec_cmd_no_error(node, cmd, sudo=True)
208 cmd = 'brctl addif {0} {1}'.format(br_name, if_2)
209 exec_cmd_no_error(node, cmd, sudo=True)
212 def linux_del_bridge(node, br_name):
213 """Delete bridge from linux node.
215 :param node: Node to delete bridge from.
216 :param br_name: Bridge name.
217 .. note:: The network interface corresponding to the bridge must be
218 down before it can be deleted!
220 cmd = 'brctl delbr {0}'.format(br_name)
221 exec_cmd_no_error(node, cmd, sudo=True)
224 def vpp_get_bridge_domain_data(node, bd_id=None):
225 """Get all bridge domain data from a VPP node. If a domain ID number is
226 provided, return only data for the matching bridge domain.
228 :param node: VPP node to get bridge domain data from.
229 :param bd_id: Numeric ID of a specific bridge domain.
232 :return: List of dictionaries containing data for each bridge domain, or
233 a single dictionary for the specified bridge domain.
236 with VatTerminal(node) as vat:
237 response = vat.vat_terminal_exec_cmd_from_template("l2_bd_dump.vat")
241 if bd_id is not None:
242 for bridge_domain in data:
243 if bridge_domain["bd_id"] == bd_id: