1 # Copyright (c) 2023 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 """Special test configurations library."""
16 from ipaddress import ip_address, AddressValueError
17 from robot.api import logger
19 from resources.libraries.python.Constants import Constants
20 from resources.libraries.python.InterfaceUtil import InterfaceUtil, \
22 from resources.libraries.python.IPAddress import IPAddress
23 from resources.libraries.python.IPUtil import IPUtil
24 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
25 from resources.libraries.python.topology import Topology
29 """Contains special test configurations implemented in python for faster
33 def vpp_create_multiple_vxlan_ipv4_tunnels(
34 node, node_vxlan_if, node_vlan_if, op_node, op_node_if,
35 n_tunnels, vni_start, src_ip_start, dst_ip_start, ip_step,
37 """Create multiple VXLAN tunnel interfaces and VLAN sub-interfaces on
40 Put each pair of VXLAN tunnel interface and VLAN sub-interface to
41 separate bridge-domain.
43 :param node: VPP node to create VXLAN tunnel interfaces.
44 :param node_vxlan_if: VPP node interface key to create VXLAN tunnel
46 :param node_vlan_if: VPP node interface key to create VLAN
48 :param op_node: Opposite VPP node for VXLAN tunnel interfaces.
49 :param op_node_if: Opposite VPP node interface key for VXLAN tunnel
51 :param n_tunnels: Number of tunnel interfaces to create.
52 :param vni_start: VNI start ID.
53 :param src_ip_start: VXLAN tunnel source IP address start.
54 :param dst_ip_start: VXLAN tunnel destination IP address start.
55 :param ip_step: IP address incremental step.
56 :param bd_id_start: Bridge-domain ID start.
58 :type node_vxlan_if: str
59 :type node_vlan_if: str
64 :type src_ip_start: str
65 :type dst_ip_start: str
67 :type bd_id_start: int
69 # configure IPs, create VXLAN interfaces and VLAN sub-interfaces
70 vxlan_count = TestConfig.vpp_create_vxlan_and_vlan_interfaces(
71 node, node_vxlan_if, node_vlan_if, n_tunnels, vni_start,
72 src_ip_start, dst_ip_start, ip_step
75 # update topology with VXLAN interfaces and VLAN sub-interfaces data
76 # and put interfaces up
77 TestConfig.vpp_put_vxlan_and_vlan_interfaces_up(
78 node, vxlan_count, node_vlan_if
81 # configure bridge domains, ARPs and routes
82 TestConfig.vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain(
83 node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start,
88 def vpp_create_vxlan_and_vlan_interfaces(
89 node, node_vxlan_if, node_vlan_if, vxlan_count, vni_start,
90 src_ip_start, dst_ip_start, ip_step):
92 Configure IPs, create VXLAN interfaces and VLAN sub-interfaces on VPP
95 :param node: VPP node.
96 :param node_vxlan_if: VPP node interface key to create VXLAN tunnel
98 :param node_vlan_if: VPP node interface key to create VLAN
100 :param vxlan_count: Number of tunnel interfaces to create.
101 :param vni_start: VNI start ID.
102 :param src_ip_start: VXLAN tunnel source IP address start.
103 :param dst_ip_start: VXLAN tunnel destination IP address start.
104 :param ip_step: IP address incremental step.
106 :type node_vxlan_if: str
107 :type node_vlan_if: str
108 :type vxlan_count: int
110 :type src_ip_start: str
111 :type dst_ip_start: str
113 :returns: Number of created VXLAN interfaces.
116 src_ip_start = ip_address(src_ip_start)
117 dst_ip_start = ip_address(dst_ip_start)
119 cmd1 = u"sw_interface_add_del_address"
121 sw_if_index=InterfaceUtil.get_interface_index(node, node_vxlan_if),
126 cmd2 = u"vxlan_add_del_tunnel_v3"
129 instance=Constants.BITWISE_NON_ZERO,
132 mcast_sw_if_index=Constants.BITWISE_NON_ZERO,
134 decap_next_index=Constants.BITWISE_NON_ZERO,
137 cmd3 = u"create_vlan_subif"
139 sw_if_index=InterfaceUtil.get_interface_index(
144 with PapiSocketExecutor(node, is_async=True) as papi_exec:
145 for i in range(0, vxlan_count):
147 src_ip = src_ip_start + i * ip_step
148 dst_ip = dst_ip_start + i * ip_step
149 except AddressValueError:
151 u"Can't do more iterations - IP address limit "
156 args1[u"prefix"] = IPUtil.create_prefix_object(
157 src_ip, 128 if src_ip_start.version == 6 else 32
159 args2[u"src_address"] = IPAddress.create_ip_address_object(
162 args2[u"dst_address"] = IPAddress.create_ip_address_object(
165 args2[u"vni"] = int(vni_start) + i
166 args3[u"vlan_id"] = i + 1
167 history = bool(not 1 < i < vxlan_count - 1)
168 papi_exec.add(cmd1, history=history, **args1)
169 papi_exec.add(cmd2, history=history, **args2)
170 papi_exec.add(cmd3, history=history, **args3)
171 papi_exec.get_replies()
176 def vpp_put_vxlan_and_vlan_interfaces_up(node, vxlan_count, node_vlan_if):
178 Update topology with VXLAN interfaces and VLAN sub-interfaces data
179 and put interfaces up.
181 :param node: VPP node.
182 :param vxlan_count: Number of tunnel interfaces.
183 :param node_vlan_if: VPP node interface key where VLAN sub-interfaces
186 :type vxlan_count: int
187 :type node_vlan_if: str
189 if_data = InterfaceUtil.vpp_get_interface_data(node)
190 cmd = u"sw_interface_set_flags"
193 flags=InterfaceStatusFlags.IF_STATUS_API_FLAG_ADMIN_UP.value
197 flags=InterfaceStatusFlags.IF_STATUS_API_FLAG_ADMIN_UP.value
200 with PapiSocketExecutor(node, is_async=True) as papi_exec:
201 for i in range(0, vxlan_count):
202 vxlan_subif_key = Topology.add_new_port(node, u"vxlan_tunnel")
203 vxlan_subif_name = f"vxlan_tunnel{i}"
204 founds = dict(vxlan=False, vlan=False)
205 vxlan_subif_idx = None
206 vlan_subif_key = Topology.add_new_port(node, u"vlan_subif")
208 f"{Topology.get_interface_name(node, node_vlan_if)}.{i+1}"
211 if not founds[u"vxlan"] \
212 and data[u"interface_name"] == vxlan_subif_name:
213 vxlan_subif_idx = data[u"sw_if_index"]
214 founds[u"vxlan"] = True
215 elif not founds[u"vlan"] \
216 and data[u"interface_name"] == vlan_subif_name:
217 vlan_idx = data[u"sw_if_index"]
218 founds[u"vlan"] = True
219 if founds[u"vxlan"] and founds[u"vlan"]:
221 Topology.update_interface_sw_if_index(
222 node, vxlan_subif_key, vxlan_subif_idx
224 Topology.update_interface_name(
225 node, vxlan_subif_key, vxlan_subif_name
227 args1[u"sw_if_index"] = vxlan_subif_idx
228 Topology.update_interface_sw_if_index(
229 node, vlan_subif_key, vlan_idx
231 Topology.update_interface_name(
232 node, vlan_subif_key, vlan_subif_name
234 args2[u"sw_if_index"] = vlan_idx
235 history = bool(not 1 < i < vxlan_count - 1)
236 papi_exec.add(cmd, history=history, **args1)
237 papi_exec.add(cmd, history=history, **args2)
238 papi_exec.get_replies()
241 def vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain(
242 node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start,
243 ip_step, bd_id_start):
245 Configure ARPs and routes for VXLAN interfaces and put each pair of
246 VXLAN tunnel interface and VLAN sub-interface to separate bridge-domain.
248 :param node: VPP node.
249 :param node_vxlan_if: VPP node interface key where VXLAN tunnel
250 interfaces have been created.
251 :param vxlan_count: Number of tunnel interfaces.
252 :param op_node: Opposite VPP node for VXLAN tunnel interfaces.
253 :param op_node_if: Opposite VPP node interface key for VXLAN tunnel
255 :param dst_ip_start: VXLAN tunnel destination IP address start.
256 :param ip_step: IP address incremental step.
257 :param bd_id_start: Bridge-domain ID start.
259 :type node_vxlan_if: str
260 :type vxlan_count: int
263 :type dst_ip_start: str
265 :type bd_id_start: int
267 dst_ip_start = ip_address(dst_ip_start)
269 cmd1 = u"ip_neighbor_add_del"
271 sw_if_index=Topology.get_interface_sw_index(node, node_vxlan_if),
273 mac_address=Topology.get_interface_mac(op_node, op_node_if),
280 cmd2 = u"ip_route_add_del"
282 interface=node_vxlan_if,
283 gateway=str(dst_ip_start)
285 route = IPUtil.compose_vpp_route_structure(
286 node, str(dst_ip_start),
287 128 if dst_ip_start.version == 6 else 32, **kwargs
294 cmd3 = u"sw_interface_set_l2_bridge"
310 with PapiSocketExecutor(node, is_async=True) as papi_exec:
311 for i in range(0, vxlan_count):
312 args1[u"neighbor"][u"ip_address"] = \
313 str(dst_ip_start + i * ip_step)
314 args2[u"route"][u"prefix"][u"address"][u"un"] = \
315 IPAddress.union_addr(dst_ip_start + i * ip_step)
316 args2[u"route"][u"paths"][0][u"nh"][u"address"] = \
317 IPAddress.union_addr(dst_ip_start + i * ip_step)
318 args3[u"rx_sw_if_index"] = Topology.get_interface_sw_index(
319 node, f"vxlan_tunnel{i+1}"
321 args3[u"bd_id"] = int(bd_id_start+i)
322 args4[u"rx_sw_if_index"] = Topology.get_interface_sw_index(
323 node, f"vlan_subif{i+1}"
325 args4[u"bd_id"] = int(bd_id_start+i)
326 history = bool(not 1 < i < vxlan_count - 1)
327 papi_exec.add(cmd1, history=history, **args1)
328 papi_exec.add(cmd2, history=history, **args2)
329 papi_exec.add(cmd3, history=history, **args3)
330 # Yes, args4 go with cmd3, there is no cmd4.
331 papi_exec.add(cmd3, history=history, **args4)
332 papi_exec.get_replies()