1 # Copyright (c) 2019 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 """GBP utilities library."""
16 from enum import IntEnum
18 from ipaddress import ip_address
20 from resources.libraries.python.IPUtil import IPUtil
21 from resources.libraries.python.L2Util import L2Util
22 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
25 class GBPEndpointFlags(IntEnum):
26 """GBP Endpoint Flags."""
27 GBP_API_ENDPOINT_FLAG_NONE = 0
28 GBP_API_ENDPOINT_FLAG_BOUNCE = 1
29 GBP_API_ENDPOINT_FLAG_REMOTE = 2
30 GBP_API_ENDPOINT_FLAG_LEARNT = 4
31 GBP_API_ENDPOINT_FLAG_EXTERNAL = 8
34 class GBPBridgeDomainFlags(IntEnum):
35 """GBP Bridge Domain Flags."""
36 GBP_BD_API_FLAG_NONE = 0
37 GBP_BD_API_FLAG_DO_NOT_LEARN = 1
38 GBP_BD_API_FLAG_UU_FWD_DROP = 2
39 GBP_BD_API_FLAG_MCAST_DROP = 4
40 GBP_BD_API_FLAG_UCAST_ARP = 8
43 class GBPSubnetType(IntEnum):
44 """GBP Subnet Type."""
45 GBP_API_SUBNET_TRANSPORT = 1
46 GBP_API_SUBNET_STITCHED_INTERNAL = 2 # pylint: disable=invalid-name
47 GBP_API_SUBNET_STITCHED_EXTERNAL = 3 # pylint: disable=invalid-name
48 GBP_API_SUBNET_L3_OUT = 4
49 GBP_API_SUBNET_ANON_L3_OUT = 5
52 class GBPExtItfFlags(IntEnum):
53 """GBP External Interface Flags."""
54 GBP_API_EXT_ITF_F_NONE = 0
55 GBP_API_EXT_ITF_F_ANON = 1
58 class GBPRuleAction(IntEnum):
59 """GBP Rule Action."""
60 GBP_API_RULE_PERMIT = 1
62 GBP_API_RULE_REDIRECT = 3
65 class GBPHashMode(IntEnum):
67 GBP_API_HASH_MODE_SRC_IP = 1
68 GBP_API_HASH_MODE_DST_IP = 2
69 GBP_API_HASH_MODE_SYMETRIC = 3
76 def gbp_route_domain_add(
77 node, rd_id=1, ip4_table_id=1, ip6_table_id=0,
78 ip4_uu_sw_if_index=0xffffffff, ip6_uu_sw_if_index=0xffffffff):
79 """Add GBP route domain.
81 :param node: Node to add GBP route domain on.
82 :param rd_id: GBP route domain ID.
83 :param ip4_table_id: IPv4 table.
84 :param ip6_table_id: IPv6 table.
85 :param ip4_uu_sw_if_index: IPv4 unicast interface index.
86 :param ip6_uu_sw_if_index: IPv6 unicast interface index.
89 :type ip4_table_id: int
90 :type ip6_table_id: int
91 :type ip4_uu_sw_if_index: int
92 :type ip6_uu_sw_if_index: int
94 cmd = u"gbp_route_domain_add"
95 err_msg = f"Failed to add GBP route domain on {node[u'host']}!"
100 ip4_table_id=ip4_table_id,
101 ip6_table_id=ip6_table_id,
102 ip4_uu_sw_if_index=ip4_uu_sw_if_index,
103 ip6_uu_sw_if_index=ip6_uu_sw_if_index
107 with PapiSocketExecutor(node) as papi_exec:
108 papi_exec.add(cmd, **args_in).get_reply(err_msg)
111 def gbp_bridge_domain_add(
112 node, bvi_sw_if_index, bd_id=1, rd_id=1,
113 uu_fwd_sw_if_index=0xffffffff, bm_flood_sw_if_index=0xffffffff):
114 """Add GBP bridge domain.
116 :param node: Node to add GBP bridge domain on.
117 :param bvi_sw_if_index: SW index of BVI/loopback interface.
118 :param bd_id: GBP bridge domain ID.
119 :param rd_id: GBP route domain ID.
120 :param uu_fwd_sw_if_index: Unicast forward interface index.
121 :param bm_flood_sw_if_index: Bcast/Mcast flood interface index.
123 :type bvi_sw_if_index: int
126 :type uu_fwd_sw_if_index: int
127 :type bm_flood_sw_if_index: int
129 cmd = u"gbp_bridge_domain_add"
130 err_msg = f"Failed to add GBP bridge domain on {node[u'host']}!"
135 GBPBridgeDomainFlags, u"GBP_BD_API_FLAG_NONE"
137 bvi_sw_if_index=bvi_sw_if_index,
138 uu_fwd_sw_if_index=uu_fwd_sw_if_index,
139 bm_flood_sw_if_index=bm_flood_sw_if_index,
145 with PapiSocketExecutor(node) as papi_exec:
146 papi_exec.add(cmd, **args_in).get_reply(err_msg)
149 def gbp_endpoint_group_add(
150 node, sclass, bd_id=1, rd_id=1, vnid=1,
151 uplink_sw_if_index=0xffffffff, remote_ep_timeout=0xffffffff):
152 """Add GBP endpoint group.
154 :param node: Node to add GBP endpoint group on.
155 :param sclass: Source CLASS.
156 :param bd_id: GBP bridge domain ID.
157 :param rd_id: GBP route domain ID.
158 :param uplink_sw_if_index: Uplink interface index.
159 :param remote_ep_timeout: Remote endpoint interface index.
166 :type uplink_sw_if_index: int
167 :type remote_ep_timeout: int
169 cmd = u"gbp_endpoint_group_add"
170 err_msg = f"Failed to add GBP endpoint group on {node[u'host']}!"
174 uplink_sw_if_index=uplink_sw_if_index,
180 remote_ep_timeout=remote_ep_timeout
185 with PapiSocketExecutor(node) as papi_exec:
186 papi_exec.add(cmd, **args_in).get_reply(err_msg)
189 def gbp_endpoint_add(node, sw_if_index, ip_addr, mac_addr, sclass):
192 :param node: Node to add GBP endpoint on.
193 :param sw_if_index: SW index of interface.
194 :param ip_addr: GBP route domain ID.
195 :param mac_addr: MAC address.
196 :param sclass: Source CLASS.
198 :type sw_if_index: int
203 cmd = u"gbp_endpoint_add"
204 err_msg = f"Failed to add GBP endpoint on {node[u'host']}!"
207 ips.append(IPUtil.create_ip_address_object(ip_address(ip_addr)))
208 tun_src = IPUtil.create_ip_address_object(ip_address(u"0.0.0.0"))
209 tun_dst = IPUtil.create_ip_address_object(ip_address(u"0.0.0.0"))
213 sw_if_index=sw_if_index,
216 mac=L2Util.mac_to_bin(mac_addr),
219 GBPEndpointFlags, u"GBP_API_ENDPOINT_FLAG_EXTERNAL"
228 with PapiSocketExecutor(node) as papi_exec:
229 papi_exec.add(cmd, **args_in).get_reply(err_msg)
232 def gbp_ext_itf_add_del(node, sw_if_index, bd_id=1, rd_id=1):
233 """Add external interface to GBP.
235 :param node: Node to add external GBP interface on.
236 :param sw_if_index: SW index of interface.
237 :param bd_id: GBP bridge domain ID.
238 :param rd_id: GBP route domain ID.
240 :type sw_if_index: int
244 cmd = u"gbp_ext_itf_add_del"
245 err_msg = u"Failed to add external GBP interface on {node[u'host']}!"
250 sw_if_index=sw_if_index,
253 flags=getattr(GBPExtItfFlags, u"GBP_API_EXT_ITF_F_NONE").value
257 with PapiSocketExecutor(node) as papi_exec:
258 papi_exec.add(cmd, **args_in).get_reply(err_msg)
261 def gbp_subnet_add_del(
262 node, address, subnet_length, sclass, rd_id=1,
263 sw_if_index=0xffffffff):
264 """Add external interface to GBP.
266 :param node: Node to add GBP subnet on.
267 :param address: IPv4 adddress.
268 :param subnet_length: IPv4 address subnet.
269 :param sclass: Source CLASS.
270 :param rd_id: GBP route domain ID.
271 :param sw_if_index: Interface index.
274 :type subnet_length: int
277 :type sw_if_index: int
279 cmd = u"gbp_subnet_add_del"
280 err_msg = f"Failed to add GBP subnet on {node[u'host']}!"
285 type=getattr(GBPSubnetType, u"GBP_API_SUBNET_L3_OUT").value,
286 sw_if_index=sw_if_index,
289 address=IPUtil.create_ip_address_object(
292 len=int(subnet_length)
298 with PapiSocketExecutor(node) as papi_exec:
299 papi_exec.add(cmd, **args_in).get_reply(err_msg)
302 def gbp_contract_add_del(node, sclass, dclass, acl_index=0, hash_mode=None):
305 :param node: Node to add GBP contract on.
306 :param sclass: Source CLASS.
307 :param dclass: Destination CLASS.
308 :param acl_index: Index of ACL rule.
309 :param hash_mode: GBP contract hash mode.
316 cmd = u"gbp_contract_add_del"
317 err_msg = f"Failed to add GBP contract on {node[u'host']}!"
319 hash_mode = u"GBP_API_HASH_MODE_SRC_IP" if hash_mode is None \
322 action=getattr(GBPRuleAction, u"GBP_API_RULE_PERMIT").value,
324 hash_mode=getattr(GBPHashMode, hash_mode).value,
329 rules = [rule_permit, rule_permit]
340 allowed_ethertypes=[0x800, 0x86dd] + [0]*14
344 with PapiSocketExecutor(node) as papi_exec:
345 papi_exec.add(cmd, **args_in).get_reply(err_msg)