d7266f58fa7a84433e2c2205372f54a62d26284b
[csit.git] / resources / libraries / python / GeneveUtil.py
1 # Copyright (c) 2021 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 """VPP GENEVE Plugin utilities library."""
15
16 from ipaddress import ip_address
17
18 from resources.libraries.python.Constants import Constants
19 from resources.libraries.python.InterfaceUtil import InterfaceUtil
20 from resources.libraries.python.IPAddress import IPAddress
21 from resources.libraries.python.IPUtil import IPUtil
22 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
23 from resources.libraries.python.topology import Topology
24
25
26 class GeneveUtil:
27     """VPP GENEVE Plugin Keywords."""
28
29     @staticmethod
30     def add_geneve_tunnel(
31             node, local_address, remote_address, vni, multicast_if=None,
32             encap_vrf=0, l3_mode=False, next_index=None):
33         """Add GENEVE tunnel on the specified VPP node.
34
35         :param node: Topology node.
36         :param local_address: Local IP address.
37         :param remote_address: Remote IP address.
38         :param vni: Virtual network ID.
39         :param multicast_if: Interface key of multicast interface; used only if
40             remote is multicast. (Default value = None)
41         :param encap_vrf: The FIB ID for sending unicast GENEVE encap packets or
42             receiving multicast packets. (Default value = 0)
43         :param l3_mode: Use geneve tunnel in L3 mode (ip routing) if Tue else in
44             L2 mode (L2 switching). (Default value = False)
45         :param next_index: The index of the next node.
46         :type node: dict
47         :type local_address: str
48         :type remote_address: str
49         :type vni: int
50         :type multicast_if: str
51         :type encap_vrf: int
52         :type l3_mode: bool
53         :type next_index: int
54         :returns: SW interface index of created geneve tunnel.
55         :rtype: int
56         """
57         cmd = u"geneve_add_del_tunnel2"
58         args = dict(
59             is_add=True,
60             local_address=IPAddress.create_ip_address_object(
61                 ip_address(local_address)
62             ),
63             remote_address=IPAddress.create_ip_address_object(
64                 ip_address(remote_address)
65             ),
66             mcast_sw_if_index=Topology.get_interface_sw_index(
67                 node, multicast_if
68             ) if multicast_if else Constants.BITWISE_NON_ZERO,
69             encap_vrf_id=int(encap_vrf),
70             decap_next_index=next_index if l3_mode
71             else Constants.BITWISE_NON_ZERO,
72             vni=int(vni),
73             l3_mode=l3_mode
74         )
75         err_msg = f"Failed to configure GENEVE tunnel on host {node[u'host']}!"
76         with PapiSocketExecutor(node) as papi_exec:
77             sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg)
78
79         if_key = Topology.add_new_port(node, u"geneve_tunnel")
80         Topology.update_interface_sw_if_index(node, if_key, sw_if_index)
81
82         ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_index)
83         Topology.update_interface_name(node, if_key, ifc_name)
84
85         ifc_mac = InterfaceUtil.vpp_get_interface_mac(node, sw_if_index)
86         Topology.update_interface_mac_address(node, if_key, ifc_mac)
87
88         return sw_if_index
89
90     @staticmethod
91     def enable_interface_geneve_bypass(node, interface, is_ipv6=False):
92         """Add ipv4/ipv6-geneve-bypass graph node for a given interface on
93         the specified VPP node.
94
95         :param node: Topology node.
96         :param interface: Interface key from topology file of interface
97             to add geneve bypass node for.
98         :param is_ipv6: Enable ipv6-geneve-bypass graph node if True else enable
99             ipv4-geneve-bypass graph node.
100         :type node: dict
101         :type interface: str
102         :type is_ipv6: bool
103         """
104         cmd = u"sw_interface_set_geneve_bypass"
105         args = dict(
106             is_ipv6=is_ipv6,
107             enable=True,
108             sw_if_index=Topology.get_interface_sw_index(node, interface)
109         )
110         err_msg = (
111             f"Failed to enable {u'ipv6' if is_ipv6 else u'ipv4'}-geneve-bypass "
112             f"on interface {interface} on host {node[u'host']}!"
113         )
114         with PapiSocketExecutor(node) as papi_exec:
115             papi_exec.add(cmd, **args).get_reply(err_msg)
116
117     @staticmethod
118     def show_geneve_tunnel_data(node):
119         """Show the GENEVE tunnels data.
120
121         :param node: DUT node.
122         :type node: dict
123         """
124         cmds = [
125             u"geneve_tunnel_dump",
126         ]
127         PapiSocketExecutor.dump_and_log(node, cmds)
128
129     @staticmethod
130     def vpp_geneve_add_multiple_tunnels(
131             node, gen_tunnel, n_tunnels, dut_if1, dut_if2, tg_if1_ip4,
132             tg_if2_ip4, tg_pf2_mac, next_idx):
133         """Create multiple GENEVE tunnels.
134
135         :param node: DUT node.
136         :param gen_tunnel: Parameters of the GENEVE tunnel.
137         :param n_tunnels: Number of tunnels.
138         :param dut_if1: The first DUT interface.
139         :param dut_if2: The second DUT interface.
140         :param tg_if1_ip4: TG interface 1 IP address.
141         :param tg_if2_ip4: TG interface 2 IP address.
142         :param tg_pf2_mac: TG interface 2 MAC address.
143         :param next_idx: The index of the next node.
144         :type node: dict
145         :type gen_tunnel: dict
146         :type n_tunnels: int
147         :type dut_if1: str
148         :type dut_if2: str
149         :type tg_if1_ip4: str
150         :type tg_if2_ip4: str
151         :type tg_pf2_mac: str
152         :type next_idx: int
153         """
154
155         src_ip_int = IPUtil.ip_to_int(gen_tunnel[u"src_ip"])
156         dst_ip_int = IPUtil.ip_to_int(gen_tunnel[u"dst_ip"])
157         if_ip_int = IPUtil.ip_to_int(gen_tunnel[u"if_ip"])
158
159         for idx in range(n_tunnels):
160             src_ip = IPUtil.int_to_ip(src_ip_int + idx * 256)
161             dst_ip = IPUtil.int_to_ip(dst_ip_int + idx * 256)
162             if_ip = IPUtil.int_to_ip(if_ip_int + idx * 256)
163
164             IPUtil.vpp_route_add(
165                 node, src_ip, gen_tunnel[u"ip_mask"],
166                 gateway=tg_if1_ip4, interface=dut_if1
167             )
168             tunnel_sw_index = GeneveUtil.add_geneve_tunnel(
169                 node, gen_tunnel[u"local"], gen_tunnel[u"remote"],
170                 gen_tunnel[u"vni"] + idx, l3_mode=True, next_index=next_idx
171             )
172             tunnel_if_key = Topology.get_interface_by_sw_index(
173                 node, tunnel_sw_index
174             )
175             tunnel_if_mac = Topology.get_interface_mac(
176                 node, tunnel_if_key
177             )
178             IPUtil.vpp_interface_set_ip_address(node, tunnel_if_key, if_ip, 24)
179             IPUtil.vpp_add_ip_neighbor(
180                 node, tunnel_if_key, tg_if2_ip4, tg_pf2_mac
181             )
182             IPUtil.vpp_route_add(
183                 node, dst_ip, gen_tunnel[u"ip_mask"],
184                 gateway=tg_if2_ip4, interface=tunnel_if_key
185             )
186             IPUtil.vpp_route_add(
187                 node, gen_tunnel[u"remote"], 32,
188                 gateway=tg_if2_ip4, interface=dut_if2
189             )
190             IPUtil.vpp_add_ip_neighbor(
191                 node, tunnel_if_key, gen_tunnel[u"local"], tunnel_if_mac
192             )
193             IPUtil.vpp_route_add(
194                 node, gen_tunnel[u"local"], 32, gateway=if_ip
195             )
196             InterfaceUtil.set_interface_state(node, tunnel_if_key, u"up")