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
17 from ipaddress import ip_address
19 from resources.libraries.python.IPUtil import IPUtil
20 from resources.libraries.python.L2Util import L2Util
21 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
22 from resources.libraries.python.topology import Topology
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
47 GBP_API_SUBNET_STITCHED_EXTERNAL = 3
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
69 def gbp_route_domain_add(
70 node, rd_id=1, ip4_table_id=1, ip6_table_id=0,
71 ip4_uu_sw_if_index=0xffffffff, ip6_uu_sw_if_index=0xffffffff):
72 """Add GBP route domain.
74 :param node: Node to add GBP route domain on.
75 :param rd_id: GBP route domain ID.
76 :param ip4_table_id: IPv4 table.
77 :param ip6_table_id: IPv6 table.
78 :param ip4_uu_sw_if_index: IPv4 unicast interface index.
79 :param ip6_uu_sw_if_index: IPv6 unicast interface index.
82 :type ip4_table_id: int
83 :type ip6_table_id: int
84 :type ip4_uu_sw_if_index: int
85 :type ip6_uu_sw_if_index: int
87 cmd = 'gbp_route_domain_add'
88 err_msg = 'Failed to add GBP route domain on {node}!'\
89 .format(node=node['host'])
94 ip4_table_id = ip4_table_id,
95 ip6_table_id = ip6_table_id,
96 ip4_uu_sw_if_index = ip4_uu_sw_if_index,
97 ip6_uu_sw_if_index = ip6_uu_sw_if_index
101 with PapiSocketExecutor(node) as papi_exec:
102 papi_exec.add(cmd, **args_in).get_reply(err_msg)
105 def gbp_bridge_domain_add(
106 node, bvi_sw_if_index, bd_id=1, rd_id=1,
107 uu_fwd_sw_if_index=0xffffffff, bm_flood_sw_if_index=0xffffffff):
108 """Add GBP bridge domain.
110 :param node: Node to add GBP bridge domain on.
111 :param bvi_sw_if_index: SW index of BVI/loopback interface.
112 :param bd_id: GBP bridge domain ID.
113 :param rd_id: GBP route domain ID.
114 :param uu_fwd_sw_if_index: Unicast forward interface index.
115 :param bm_flood_sw_if_index: Bcast/Mcast flood interface index.
117 :type bvi_sw_if_index: int
120 :type uu_fwd_sw_if_index: int
121 :type bm_flood_sw_if_index: int
123 cmd = 'gbp_bridge_domain_add'
124 err_msg = 'Failed to add GBP bridge domain on {node}!'\
125 .format(node=node['host'])
129 flags = getattr(GBPBridgeDomainFlags,
130 'GBP_BD_API_FLAG_NONE').value,
131 bvi_sw_if_index = bvi_sw_if_index,
132 uu_fwd_sw_if_index = uu_fwd_sw_if_index,
133 bm_flood_sw_if_index = bm_flood_sw_if_index,
139 with PapiSocketExecutor(node) as papi_exec:
140 papi_exec.add(cmd, **args_in).get_reply(err_msg)
143 def gbp_endpoint_group_add(
144 node, sclass, bd_id=1, rd_id=1, vnid=1,
145 uplink_sw_if_index=0xffffffff, remote_ep_timeout=0xffffffff):
146 """Add GBP endpoint group.
148 :param node: Node to add GBP endpoint group on.
149 :param sclass: Source CLASS.
150 :param bd_id: GBP bridge domain ID.
151 :param rd_id: GBP route domain ID.
152 :param uplink_sw_if_index: Uplink interface index.
153 :param remote_ep_timeout: Remote endpoint interface index.
160 :type uplink_sw_if_index: int
161 :type remote_ep_timeout: int
163 cmd = 'gbp_endpoint_group_add'
164 err_msg = 'Failed to add GBP endpoint group on {node}!'\
165 .format(node=node['host'])
169 uplink_sw_if_index = uplink_sw_if_index,
175 remote_ep_timeout = remote_ep_timeout
180 with PapiSocketExecutor(node) as papi_exec:
181 papi_exec.add(cmd, **args_in).get_reply(err_msg)
184 def gbp_endpoint_add(node, sw_if_index, ip_addr, mac_addr, sclass):
187 :param node: Node to add GBP endpoint on.
188 :param sw_if_index: SW index of interface.
189 :param ip_addr: GBP route domain ID.
190 :param mac_addr: MAC address.
191 :param sclass: Source CLASS.
193 :type sw_if_index: int
198 cmd = 'gbp_endpoint_add'
199 err_msg = 'Failed to add GBP endpoint on {node}!'\
200 .format(node=node['host'])
203 ips.append(IPUtil.create_ip_address_object(
204 ip_address(unicode(ip_addr))))
205 tun_src = IPUtil.create_ip_address_object(
206 ip_address(unicode('0.0.0.0')))
207 tun_dst = IPUtil.create_ip_address_object(
208 ip_address(unicode('0.0.0.0')))
212 sw_if_index = sw_if_index,
215 mac = L2Util.mac_to_bin(mac_addr),
217 flags = getattr(GBPEndpointFlags,
218 'GBP_API_ENDPOINT_FLAG_EXTERNAL').value,
226 with PapiSocketExecutor(node) as papi_exec:
227 papi_exec.add(cmd, **args_in).get_reply(err_msg)
230 def gbp_ext_itf_add_del(node, sw_if_index, bd_id=1, rd_id=1):
231 """Add external interface to GBP.
233 :param node: Node to add external GBP interface on.
234 :param sw_if_index: SW index of interface.
235 :param bd_id: GBP bridge domain ID.
236 :param rd_id: GBP route domain ID.
238 :type sw_if_index: int
242 cmd = 'gbp_ext_itf_add_del'
243 err_msg = 'Failed to add external GBP interface on {node}!'\
244 .format(node=node['host'])
249 sw_if_index = sw_if_index,
252 flags = getattr(GBPExtItfFlags,
253 '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 = 'gbp_subnet_add_del'
280 err_msg = 'Failed to add GBP subnet on {node}!'\
281 .format(node=node['host'])
286 type = getattr(GBPSubnetType,
287 'GBP_API_SUBNET_L3_OUT').value,
288 sw_if_index = sw_if_index,
291 address = IPUtil.create_ip_address_object(
292 ip_address(unicode(address))),
293 len = int(subnet_length)
299 with PapiSocketExecutor(node) as papi_exec:
300 papi_exec.add(cmd, **args_in).get_reply(err_msg)
303 def gbp_contract_add_del(node, sclass, dclass, acl_index=0):
306 :param node: Node to add GBP contract on.
307 :param sclass: Source CLASS.
308 :param dclass: Destination CLASS.
309 :param acl_index: Index of ACL rule.
315 cmd = 'gbp_contract_add_del'
316 err_msg = 'Failed to add GBP contract on {node}!'\
317 .format(node=node['host'])
320 action = getattr(GBPRuleAction,
321 'GBP_API_RULE_PERMIT').value,
328 rules = [rule_permit, rule_permit]
333 acl_index = acl_index,
336 n_rules = len(rules),
339 allowed_ethertypes = [0x800, 0x86dd] + [0]*14
343 with PapiSocketExecutor(node) as papi_exec:
344 papi_exec.add(cmd, **args_in).get_reply(err_msg)