backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / services / protocols / bgp / api / prefix.py
1 # Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 """
17  Prefix related APIs.
18 """
19 import logging
20
21 from ryu.lib.packet.bgp import EvpnEsi
22 from ryu.lib.packet.bgp import EvpnNLRI
23 from ryu.lib.packet.bgp import EvpnEthernetAutoDiscoveryNLRI
24 from ryu.lib.packet.bgp import EvpnMacIPAdvertisementNLRI
25 from ryu.lib.packet.bgp import EvpnInclusiveMulticastEthernetTagNLRI
26 from ryu.lib.packet.bgp import EvpnEthernetSegmentNLRI
27 from ryu.lib.packet.bgp import EvpnIpPrefixNLRI
28 from ryu.lib.packet.bgp import BGPPathAttributePmsiTunnel
29 from ryu.lib.packet.bgp import FlowSpecIPv4NLRI
30 from ryu.lib.packet.bgp import FlowSpecIPv6NLRI
31 from ryu.lib.packet.bgp import FlowSpecVPNv4NLRI
32 from ryu.lib.packet.bgp import FlowSpecVPNv6NLRI
33 from ryu.lib.packet.bgp import FlowSpecL2VPNNLRI
34 from ryu.lib.packet.bgp import BGPFlowSpecTrafficRateCommunity
35 from ryu.lib.packet.bgp import BGPFlowSpecTrafficActionCommunity
36 from ryu.lib.packet.bgp import BGPFlowSpecRedirectCommunity
37 from ryu.lib.packet.bgp import BGPFlowSpecTrafficMarkingCommunity
38 from ryu.lib.packet.bgp import BGPFlowSpecVlanActionCommunity
39 from ryu.lib.packet.bgp import BGPFlowSpecTPIDActionCommunity
40
41 from ryu.services.protocols.bgp.api.base import EVPN_ROUTE_TYPE
42 from ryu.services.protocols.bgp.api.base import EVPN_ESI
43 from ryu.services.protocols.bgp.api.base import EVPN_ETHERNET_TAG_ID
44 from ryu.services.protocols.bgp.api.base import REDUNDANCY_MODE
45 from ryu.services.protocols.bgp.api.base import MAC_ADDR
46 from ryu.services.protocols.bgp.api.base import IP_ADDR
47 from ryu.services.protocols.bgp.api.base import IP_PREFIX
48 from ryu.services.protocols.bgp.api.base import GW_IP_ADDR
49 from ryu.services.protocols.bgp.api.base import MPLS_LABELS
50 from ryu.services.protocols.bgp.api.base import NEXT_HOP
51 from ryu.services.protocols.bgp.api.base import PREFIX
52 from ryu.services.protocols.bgp.api.base import RegisterWithArgChecks
53 from ryu.services.protocols.bgp.api.base import ROUTE_DISTINGUISHER
54 from ryu.services.protocols.bgp.api.base import VPN_LABEL
55 from ryu.services.protocols.bgp.api.base import EVPN_VNI
56 from ryu.services.protocols.bgp.api.base import TUNNEL_TYPE
57 from ryu.services.protocols.bgp.api.base import PMSI_TUNNEL_TYPE
58 from ryu.services.protocols.bgp.api.base import FLOWSPEC_FAMILY
59 from ryu.services.protocols.bgp.api.base import FLOWSPEC_RULES
60 from ryu.services.protocols.bgp.api.base import FLOWSPEC_ACTIONS
61 from ryu.services.protocols.bgp.base import add_bgp_error_metadata
62 from ryu.services.protocols.bgp.base import PREFIX_ERROR_CODE
63 from ryu.services.protocols.bgp.base import validate
64 from ryu.services.protocols.bgp.core import BgpCoreError
65 from ryu.services.protocols.bgp.core_manager import CORE_MANAGER
66 from ryu.services.protocols.bgp.rtconf.base import ConfigValueError
67 from ryu.services.protocols.bgp.rtconf.base import RuntimeConfigError
68 from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF
69 from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4
70 from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_L2_EVPN
71 from ryu.services.protocols.bgp.utils import validation
72
73 LOG = logging.getLogger('bgpspeaker.api.prefix')
74
75 # Maximum value of the Ethernet Tag ID
76 EVPN_MAX_ET = EvpnNLRI.MAX_ET
77
78 # ESI Types
79 ESI_TYPE_ARBITRARY = EvpnEsi.ARBITRARY
80 ESI_TYPE_LACP = EvpnEsi.LACP
81 ESI_TYPE_L2_BRIDGE = EvpnEsi.L2_BRIDGE
82 ESI_TYPE_MAC_BASED = EvpnEsi.MAC_BASED
83 ESI_TYPE_ROUTER_ID = EvpnEsi.ROUTER_ID
84 ESI_TYPE_AS_BASED = EvpnEsi.AS_BASED
85 SUPPORTED_ESI_TYPES = [
86     ESI_TYPE_ARBITRARY,
87     ESI_TYPE_LACP,
88     ESI_TYPE_L2_BRIDGE,
89     ESI_TYPE_MAC_BASED,
90     ESI_TYPE_ROUTER_ID,
91     ESI_TYPE_AS_BASED,
92 ]
93
94 # Constants used in API calls for EVPN
95 EVPN_ETH_AUTO_DISCOVERY = EvpnEthernetAutoDiscoveryNLRI.ROUTE_TYPE_NAME
96 EVPN_MAC_IP_ADV_ROUTE = EvpnMacIPAdvertisementNLRI.ROUTE_TYPE_NAME
97 EVPN_MULTICAST_ETAG_ROUTE = (
98     EvpnInclusiveMulticastEthernetTagNLRI.ROUTE_TYPE_NAME)
99 EVPN_ETH_SEGMENT = EvpnEthernetSegmentNLRI.ROUTE_TYPE_NAME
100 EVPN_IP_PREFIX_ROUTE = EvpnIpPrefixNLRI.ROUTE_TYPE_NAME
101 SUPPORTED_EVPN_ROUTE_TYPES = [
102     EVPN_ETH_AUTO_DISCOVERY,
103     EVPN_MAC_IP_ADV_ROUTE,
104     EVPN_MULTICAST_ETAG_ROUTE,
105     EVPN_ETH_SEGMENT,
106     EVPN_IP_PREFIX_ROUTE,
107 ]
108
109 # Constants used in API calls for Flow Specification
110 FLOWSPEC_FAMILY_IPV4 = FlowSpecIPv4NLRI.FLOWSPEC_FAMILY
111 FLOWSPEC_FAMILY_IPV6 = FlowSpecIPv6NLRI.FLOWSPEC_FAMILY
112 FLOWSPEC_FAMILY_VPNV4 = FlowSpecVPNv4NLRI.FLOWSPEC_FAMILY
113 FLOWSPEC_FAMILY_VPNV6 = FlowSpecVPNv6NLRI.FLOWSPEC_FAMILY
114 FLOWSPEC_FAMILY_L2VPN = FlowSpecL2VPNNLRI.FLOWSPEC_FAMILY
115 SUPPORTED_FLOWSPEC_FAMILIES = (
116     FLOWSPEC_FAMILY_IPV4,
117     FLOWSPEC_FAMILY_IPV6,
118     FLOWSPEC_FAMILY_VPNV4,
119     FLOWSPEC_FAMILY_VPNV6,
120     FLOWSPEC_FAMILY_L2VPN,
121 )
122
123 # Constants for the Traffic Filtering Actions of Flow Specification
124 # Constants for the Traffic Filtering Actions of Flow Specification.
125 FLOWSPEC_ACTION_TRAFFIC_RATE = BGPFlowSpecTrafficRateCommunity.ACTION_NAME
126 FLOWSPEC_ACTION_TRAFFIC_ACTION = BGPFlowSpecTrafficActionCommunity.ACTION_NAME
127 FLOWSPEC_ACTION_REDIRECT = BGPFlowSpecRedirectCommunity.ACTION_NAME
128 FLOWSPEC_ACTION_TRAFFIC_MARKING = BGPFlowSpecTrafficMarkingCommunity.ACTION_NAME
129 FLOWSPEC_ACTION_VLAN = BGPFlowSpecVlanActionCommunity.ACTION_NAME
130 FLOWSPEC_ACTION_TPID = BGPFlowSpecTPIDActionCommunity.ACTION_NAME
131
132 SUPPORTTED_FLOWSPEC_ACTIONS = (
133     FLOWSPEC_ACTION_TRAFFIC_RATE,
134     FLOWSPEC_ACTION_TRAFFIC_ACTION,
135     FLOWSPEC_ACTION_REDIRECT,
136     FLOWSPEC_ACTION_TRAFFIC_MARKING,
137     FLOWSPEC_ACTION_VLAN,
138     FLOWSPEC_ACTION_TPID,
139 )
140
141
142 # Constants for ESI Label extended community
143 REDUNDANCY_MODE_ALL_ACTIVE = 'all_active'
144 REDUNDANCY_MODE_SINGLE_ACTIVE = 'single_active'
145 SUPPORTED_REDUNDANCY_MODES = [
146     REDUNDANCY_MODE_ALL_ACTIVE,
147     REDUNDANCY_MODE_SINGLE_ACTIVE,
148 ]
149
150 # Constants for BGP Tunnel Encapsulation Attribute
151 TUNNEL_TYPE_VXLAN = 'vxlan'
152 TUNNEL_TYPE_NVGRE = 'nvgre'
153 TUNNEL_TYPE_MPLS = 'mpls'
154 TUNNEL_TYPE_MPLS_IN_GRE = 'mpls_in_gre'
155 TUNNEL_TYPE_VXLAN_GRE = 'vxlan_gre'
156 SUPPORTED_TUNNEL_TYPES = [
157     TUNNEL_TYPE_VXLAN,
158     TUNNEL_TYPE_NVGRE,
159     TUNNEL_TYPE_MPLS,
160     TUNNEL_TYPE_MPLS_IN_GRE,
161     TUNNEL_TYPE_VXLAN_GRE,
162 ]
163 # Constants for PMSI Tunnel Attribute
164 PMSI_TYPE_NO_TUNNEL_INFO = (
165     BGPPathAttributePmsiTunnel.TYPE_NO_TUNNEL_INFORMATION_PRESENT
166 )
167 PMSI_TYPE_INGRESS_REP = (
168     BGPPathAttributePmsiTunnel.TYPE_INGRESS_REPLICATION
169 )
170 SUPPORTED_PMSI_TUNNEL_TYPES = [
171     PMSI_TYPE_NO_TUNNEL_INFO,
172     PMSI_TYPE_INGRESS_REP,
173 ]
174
175
176 @add_bgp_error_metadata(code=PREFIX_ERROR_CODE,
177                         sub_code=1,
178                         def_desc='Unknown error related to operation on '
179                         'prefixes')
180 class PrefixError(RuntimeConfigError):
181     pass
182
183
184 @validate(name=PREFIX)
185 def is_valid_prefix(prefix):
186     if not (validation.is_valid_ipv4_prefix(prefix)
187             or validation.is_valid_ipv6_prefix(prefix)):
188         raise ConfigValueError(conf_name=PREFIX,
189                                conf_value=prefix)
190
191
192 @validate(name=NEXT_HOP)
193 def is_valid_next_hop(next_hop):
194     if not (validation.is_valid_ipv4(next_hop)
195             or validation.is_valid_ipv6(next_hop)):
196         raise ConfigValueError(conf_name=NEXT_HOP,
197                                conf_value=next_hop)
198
199
200 @validate(name=EVPN_ROUTE_TYPE)
201 def is_valid_evpn_route_type(route_type):
202     if route_type not in SUPPORTED_EVPN_ROUTE_TYPES:
203         raise ConfigValueError(conf_name=EVPN_ROUTE_TYPE,
204                                conf_value=route_type)
205
206
207 @validate(name=EVPN_ESI)
208 def is_valid_esi(esi):
209     if not validation.is_valid_esi(esi):
210         raise ConfigValueError(conf_name=EVPN_ESI,
211                                conf_value=esi)
212
213
214 @validate(name=EVPN_ETHERNET_TAG_ID)
215 def is_valid_ethernet_tag_id(ethernet_tag_id):
216     if not validation.is_valid_ethernet_tag_id(ethernet_tag_id):
217         raise ConfigValueError(conf_name=EVPN_ETHERNET_TAG_ID,
218                                conf_value=ethernet_tag_id)
219
220
221 @validate(name=REDUNDANCY_MODE)
222 def is_valid_redundancy_mode(redundancy_mode):
223     if redundancy_mode not in SUPPORTED_REDUNDANCY_MODES:
224         raise ConfigValueError(conf_name=REDUNDANCY_MODE,
225                                conf_value=redundancy_mode)
226
227
228 @validate(name=MAC_ADDR)
229 def is_valid_mac_addr(addr):
230     if not validation.is_valid_mac(addr):
231         raise ConfigValueError(conf_name=MAC_ADDR,
232                                conf_value=addr)
233
234
235 @validate(name=IP_ADDR)
236 def is_valid_ip_addr(addr):
237     # Note: Allows empty IP Address (means length=0).
238     # e.g.) L2VPN MAC advertisement of Cisco NX-OS
239     if not (addr is None
240             or validation.is_valid_ipv4(addr)
241             or validation.is_valid_ipv6(addr)):
242         raise ConfigValueError(conf_name=IP_ADDR,
243                                conf_value=addr)
244
245
246 @validate(name=IP_PREFIX)
247 def is_valid_ip_prefix(prefix):
248     if not (validation.is_valid_ipv4_prefix(prefix)
249             or validation.is_valid_ipv6_prefix(prefix)):
250         raise ConfigValueError(conf_name=IP_PREFIX,
251                                conf_value=prefix)
252
253
254 @validate(name=GW_IP_ADDR)
255 def is_valid_gw_ip_addr(addr):
256     if not (validation.is_valid_ipv4(addr)
257             or validation.is_valid_ipv6(addr)):
258         raise ConfigValueError(conf_name=GW_IP_ADDR,
259                                conf_value=addr)
260
261
262 @validate(name=MPLS_LABELS)
263 def is_valid_mpls_labels(labels):
264     if not validation.is_valid_mpls_labels(labels):
265         raise ConfigValueError(conf_name=MPLS_LABELS,
266                                conf_value=labels)
267
268
269 @validate(name=EVPN_VNI)
270 def is_valid_vni(vni):
271     if not validation.is_valid_vni(vni):
272         raise ConfigValueError(conf_name=EVPN_VNI,
273                                conf_value=vni)
274
275
276 @validate(name=TUNNEL_TYPE)
277 def is_valid_tunnel_type(tunnel_type):
278     if tunnel_type not in SUPPORTED_TUNNEL_TYPES:
279         raise ConfigValueError(conf_name=TUNNEL_TYPE,
280                                conf_value=tunnel_type)
281
282
283 @validate(name=PMSI_TUNNEL_TYPE)
284 def is_valid_pmsi_tunnel_type(pmsi_tunnel_type):
285     if pmsi_tunnel_type not in SUPPORTED_PMSI_TUNNEL_TYPES:
286         raise ConfigValueError(conf_name=PMSI_TUNNEL_TYPE,
287                                conf_value=pmsi_tunnel_type)
288
289
290 @validate(name=FLOWSPEC_FAMILY)
291 def is_valid_flowspec_family(flowspec_family):
292     if flowspec_family not in SUPPORTED_FLOWSPEC_FAMILIES:
293         raise ConfigValueError(conf_name=FLOWSPEC_FAMILY,
294                                conf_value=flowspec_family)
295
296
297 @validate(name=FLOWSPEC_RULES)
298 def is_valid_flowspec_rules(rules):
299     if not isinstance(rules, dict):
300         raise ConfigValueError(conf_name=FLOWSPEC_RULES,
301                                conf_value=rules)
302
303
304 @validate(name=FLOWSPEC_ACTIONS)
305 def is_valid_flowspec_actions(actions):
306     for k in actions:
307         if k not in SUPPORTTED_FLOWSPEC_ACTIONS:
308             raise ConfigValueError(conf_name=FLOWSPEC_ACTIONS,
309                                    conf_value=actions)
310
311
312 @RegisterWithArgChecks(name='prefix.add_local',
313                        req_args=[ROUTE_DISTINGUISHER, PREFIX, NEXT_HOP],
314                        opt_args=[VRF_RF])
315 def add_local(route_dist, prefix, next_hop, route_family=VRF_RF_IPV4):
316     """Adds *prefix* from VRF identified by *route_dist* and sets the source as
317     network controller.
318     """
319     try:
320         # Create new path and insert into appropriate VRF table.
321         tm = CORE_MANAGER.get_core_service().table_manager
322         label = tm.update_vrf_table(route_dist, prefix, next_hop, route_family)
323         # Currently we only allocate one label per local_prefix,
324         # so we share first label from the list.
325         if label:
326             label = label[0]
327
328         # Send success response with new label.
329         return [{ROUTE_DISTINGUISHER: route_dist, PREFIX: prefix,
330                  VRF_RF: route_family, VPN_LABEL: label}]
331     except BgpCoreError as e:
332         raise PrefixError(desc=e)
333
334
335 @RegisterWithArgChecks(name='prefix.delete_local',
336                        req_args=[ROUTE_DISTINGUISHER, PREFIX],
337                        opt_args=[VRF_RF])
338 def delete_local(route_dist, prefix, route_family=VRF_RF_IPV4):
339     """Deletes/withdraws *prefix* from VRF identified by *route_dist* and
340     source as network controller.
341     """
342     try:
343         tm = CORE_MANAGER.get_core_service().table_manager
344         tm.update_vrf_table(route_dist, prefix,
345                             route_family=route_family, is_withdraw=True)
346         # Send success response.
347         return [{ROUTE_DISTINGUISHER: route_dist, PREFIX: prefix,
348                  VRF_RF: route_family}]
349     except BgpCoreError as e:
350         raise PrefixError(desc=e)
351
352
353 # =============================================================================
354 # BGP EVPN Routes related APIs
355 # =============================================================================
356
357 @RegisterWithArgChecks(name='evpn_prefix.add_local',
358                        req_args=[EVPN_ROUTE_TYPE, ROUTE_DISTINGUISHER,
359                                  NEXT_HOP],
360                        opt_args=[EVPN_ESI, EVPN_ETHERNET_TAG_ID,
361                                  REDUNDANCY_MODE, MAC_ADDR, IP_ADDR, IP_PREFIX,
362                                  GW_IP_ADDR, EVPN_VNI, TUNNEL_TYPE,
363                                  PMSI_TUNNEL_TYPE])
364 def add_evpn_local(route_type, route_dist, next_hop, **kwargs):
365     """Adds EVPN route from VRF identified by *route_dist*.
366     """
367
368     if(route_type in [EVPN_ETH_AUTO_DISCOVERY, EVPN_ETH_SEGMENT]
369        and kwargs['esi'] == 0):
370         raise ConfigValueError(conf_name=EVPN_ESI,
371                                conf_value=kwargs['esi'])
372
373     try:
374         # Create new path and insert into appropriate VRF table.
375         tm = CORE_MANAGER.get_core_service().table_manager
376         label = tm.update_vrf_table(route_dist, next_hop=next_hop,
377                                     route_family=VRF_RF_L2_EVPN,
378                                     route_type=route_type, **kwargs)
379         # Currently we only allocate one label per local route,
380         # so we share first label from the list.
381         if label:
382             label = label[0]
383
384         # Send success response with new label.
385         return [{EVPN_ROUTE_TYPE: route_type,
386                  ROUTE_DISTINGUISHER: route_dist,
387                  VRF_RF: VRF_RF_L2_EVPN,
388                  VPN_LABEL: label}.update(kwargs)]
389     except BgpCoreError as e:
390         raise PrefixError(desc=e)
391
392
393 @RegisterWithArgChecks(name='evpn_prefix.delete_local',
394                        req_args=[EVPN_ROUTE_TYPE, ROUTE_DISTINGUISHER],
395                        opt_args=[EVPN_ESI, EVPN_ETHERNET_TAG_ID, MAC_ADDR,
396                                  IP_ADDR, IP_PREFIX, EVPN_VNI])
397 def delete_evpn_local(route_type, route_dist, **kwargs):
398     """Deletes/withdraws EVPN route from VRF identified by *route_dist*.
399     """
400     try:
401         tm = CORE_MANAGER.get_core_service().table_manager
402         tm.update_vrf_table(route_dist,
403                             route_family=VRF_RF_L2_EVPN,
404                             route_type=route_type, is_withdraw=True, **kwargs)
405         # Send success response.
406         return [{EVPN_ROUTE_TYPE: route_type,
407                  ROUTE_DISTINGUISHER: route_dist,
408                  VRF_RF: VRF_RF_L2_EVPN}.update(kwargs)]
409     except BgpCoreError as e:
410         raise PrefixError(desc=e)
411
412
413 # =============================================================================
414 # BGP Flow Specification Routes related APIs
415 # =============================================================================
416
417 @RegisterWithArgChecks(
418     name='flowspec.add_local',
419     req_args=[FLOWSPEC_FAMILY, ROUTE_DISTINGUISHER, FLOWSPEC_RULES],
420     opt_args=[FLOWSPEC_ACTIONS])
421 def add_flowspec_local(flowspec_family, route_dist, rules, **kwargs):
422     """Adds Flow Specification route from VRF identified by *route_dist*.
423     """
424     try:
425         # Create new path and insert into appropriate VRF table.
426         tm = CORE_MANAGER.get_core_service().table_manager
427         tm.update_flowspec_vrf_table(
428             flowspec_family=flowspec_family, route_dist=route_dist,
429             rules=rules, **kwargs)
430
431         # Send success response.
432         return [{FLOWSPEC_FAMILY: flowspec_family,
433                  ROUTE_DISTINGUISHER: route_dist,
434                  FLOWSPEC_RULES: rules}.update(kwargs)]
435
436     except BgpCoreError as e:
437         raise PrefixError(desc=e)
438
439
440 @RegisterWithArgChecks(
441     name='flowspec.del_local',
442     req_args=[FLOWSPEC_FAMILY, ROUTE_DISTINGUISHER, FLOWSPEC_RULES])
443 def del_flowspec_local(flowspec_family, route_dist, rules):
444     """Deletes/withdraws Flow Specification route from VRF identified
445     by *route_dist*.
446     """
447     try:
448         tm = CORE_MANAGER.get_core_service().table_manager
449         tm.update_flowspec_vrf_table(
450             flowspec_family=flowspec_family, route_dist=route_dist,
451             rules=rules, is_withdraw=True)
452
453         # Send success response.
454         return [{FLOWSPEC_FAMILY: flowspec_family,
455                  ROUTE_DISTINGUISHER: route_dist,
456                  FLOWSPEC_RULES: rules}]
457
458     except BgpCoreError as e:
459         raise PrefixError(desc=e)