backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / services / protocols / bgp / utils / bgp.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  Utilities related to bgp data types and models.
18 """
19 import logging
20
21 import netaddr
22
23 from ryu.lib import ip
24 from ryu.lib.packet.bgp import (
25     BGPUpdate,
26     RF_IPv4_UC,
27     RF_IPv6_UC,
28     RF_IPv4_VPN,
29     RF_IPv6_VPN,
30     RF_L2_EVPN,
31     RF_IPv4_FLOWSPEC,
32     RF_IPv6_FLOWSPEC,
33     RF_VPNv4_FLOWSPEC,
34     RF_VPNv6_FLOWSPEC,
35     RF_L2VPN_FLOWSPEC,
36     RF_RTC_UC,
37     RouteTargetMembershipNLRI,
38     BGP_ATTR_TYPE_MULTI_EXIT_DISC,
39     BGPPathAttributeMultiExitDisc,
40     BGPPathAttributeMpUnreachNLRI,
41     BGPPathAttributeAs4Path,
42     BGPPathAttributeAs4Aggregator,
43     BGPPathAttributeUnknown,
44     BGP_ATTR_FLAG_OPTIONAL,
45     BGP_ATTR_FLAG_TRANSITIVE,
46     BGPTwoOctetAsSpecificExtendedCommunity,
47     BGPIPv4AddressSpecificExtendedCommunity,
48     BGPFourOctetAsSpecificExtendedCommunity,
49     BGPFlowSpecTrafficRateCommunity,
50     BGPFlowSpecTrafficActionCommunity,
51     BGPFlowSpecRedirectCommunity,
52     BGPFlowSpecTrafficMarkingCommunity,
53     BGPFlowSpecVlanActionCommunity,
54     BGPFlowSpecTPIDActionCommunity,
55 )
56 from ryu.services.protocols.bgp.info_base.rtc import RtcPath
57 from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Path
58 from ryu.services.protocols.bgp.info_base.ipv6 import Ipv6Path
59 from ryu.services.protocols.bgp.info_base.vpnv4 import Vpnv4Path
60 from ryu.services.protocols.bgp.info_base.vpnv6 import Vpnv6Path
61 from ryu.services.protocols.bgp.info_base.evpn import EvpnPath
62 from ryu.services.protocols.bgp.info_base.ipv4fs import IPv4FlowSpecPath
63 from ryu.services.protocols.bgp.info_base.ipv6fs import IPv6FlowSpecPath
64 from ryu.services.protocols.bgp.info_base.vpnv4fs import VPNv4FlowSpecPath
65 from ryu.services.protocols.bgp.info_base.vpnv6fs import VPNv6FlowSpecPath
66 from ryu.services.protocols.bgp.info_base.l2vpnfs import L2VPNFlowSpecPath
67
68
69 LOG = logging.getLogger('utils.bgp')
70
71 # RouteFamily to path sub-class mapping.
72 _ROUTE_FAMILY_TO_PATH_MAP = {RF_IPv4_UC: Ipv4Path,
73                              RF_IPv6_UC: Ipv6Path,
74                              RF_IPv4_VPN: Vpnv4Path,
75                              RF_IPv6_VPN: Vpnv6Path,
76                              RF_L2_EVPN: EvpnPath,
77                              RF_IPv4_FLOWSPEC: IPv4FlowSpecPath,
78                              RF_IPv6_FLOWSPEC: IPv6FlowSpecPath,
79                              RF_VPNv4_FLOWSPEC: VPNv4FlowSpecPath,
80                              RF_VPNv6_FLOWSPEC: VPNv6FlowSpecPath,
81                              RF_L2VPN_FLOWSPEC: L2VPNFlowSpecPath,
82                              RF_RTC_UC: RtcPath}
83
84
85 def create_path(src_peer, nlri, **kwargs):
86     route_family = nlri.ROUTE_FAMILY
87     assert route_family in _ROUTE_FAMILY_TO_PATH_MAP.keys()
88     path_cls = _ROUTE_FAMILY_TO_PATH_MAP.get(route_family)
89     return path_cls(src_peer, nlri, src_peer.version_num, **kwargs)
90
91
92 def clone_path_and_update_med_for_target_neighbor(path, med):
93     assert path and med
94     route_family = path.route_family
95     if route_family not in _ROUTE_FAMILY_TO_PATH_MAP.keys():
96         raise ValueError('Clone is not supported for address-family %s' %
97                          route_family)
98     path_cls = _ROUTE_FAMILY_TO_PATH_MAP.get(route_family)
99     pattrs = path.pathattr_map
100     pattrs[BGP_ATTR_TYPE_MULTI_EXIT_DISC] = BGPPathAttributeMultiExitDisc(med)
101     return path_cls(
102         path.source, path.nlri, path.source_version_num,
103         pattrs=pattrs, nexthop=path.nexthop,
104         is_withdraw=path.is_withdraw,
105         med_set_by_target_neighbor=True
106     )
107
108
109 def clone_rtcpath_update_rt_as(path, new_rt_as):
110     """Clones given RT NLRI `path`, and updates it with new RT_NLRI AS.
111
112         Parameters:
113             - `path`: (Path) RT_NLRI path
114             - `new_rt_as`: AS value of cloned paths' RT_NLRI
115     """
116     assert path and new_rt_as
117     if not path or path.route_family != RF_RTC_UC:
118         raise ValueError('Expected RT_NLRI path')
119     old_nlri = path.nlri
120     new_rt_nlri = RouteTargetMembershipNLRI(new_rt_as, old_nlri.route_target)
121     return RtcPath(path.source, new_rt_nlri, path.source_version_num,
122                    pattrs=path.pathattr_map, nexthop=path.nexthop,
123                    is_withdraw=path.is_withdraw)
124
125
126 def from_inet_ptoi(bgp_id):
127     """Convert an IPv4 address string format to a four byte long.
128     """
129     four_byte_id = None
130     try:
131         four_byte_id = ip.ipv4_to_int(bgp_id)
132     except ValueError:
133         LOG.debug('Invalid bgp id given for conversion to integer value %s',
134                   bgp_id)
135
136     return four_byte_id
137
138
139 def get_unknown_opttrans_attr(path):
140     """Utility method that gives a `dict` of unknown and unsupported optional
141     transitive path attributes of `path`.
142
143     Returns dict: <key> - attribute type code, <value> - unknown path-attr.
144     """
145     path_attrs = path.pathattr_map
146     unknown_opt_tran_attrs = {}
147     for _, attr in path_attrs.items():
148         if (isinstance(attr, BGPPathAttributeUnknown) and
149                 attr.flags & (BGP_ATTR_FLAG_OPTIONAL |
150                               BGP_ATTR_FLAG_TRANSITIVE)) or \
151                 isinstance(attr, BGPPathAttributeAs4Path) or \
152                 isinstance(attr, BGPPathAttributeAs4Aggregator):
153             unknown_opt_tran_attrs[attr.type] = attr
154
155     return unknown_opt_tran_attrs
156
157
158 def create_end_of_rib_update():
159     """Construct end-of-rib (EOR) Update instance."""
160     mpunreach_attr = BGPPathAttributeMpUnreachNLRI(RF_IPv4_VPN.afi,
161                                                    RF_IPv4_VPN.safi,
162                                                    [])
163     eor = BGPUpdate(path_attributes=[mpunreach_attr])
164     return eor
165
166
167 # Bgp update message instance that can used as End of RIB marker.
168 UPDATE_EOR = create_end_of_rib_update()
169
170
171 def create_rt_extended_community(value, subtype=2):
172     """
173     Creates an instance of the BGP Route Target Community (if "subtype=2")
174     or Route Origin Community ("subtype=3").
175
176     :param value: String of Route Target or Route Origin value.
177     :param subtype: Subtype of Extended Community.
178     :return: An instance of Route Target or Route Origin Community.
179     """
180     global_admin, local_admin = value.split(':')
181     local_admin = int(local_admin)
182     if global_admin.isdigit() and 0 <= int(global_admin) <= 0xffff:
183         ext_com = BGPTwoOctetAsSpecificExtendedCommunity(
184             subtype=subtype,
185             as_number=int(global_admin),
186             local_administrator=local_admin)
187     elif global_admin.isdigit() and 0xffff < int(global_admin) <= 0xffffffff:
188         ext_com = BGPFourOctetAsSpecificExtendedCommunity(
189             subtype=subtype,
190             as_number=int(global_admin),
191             local_administrator=local_admin)
192     elif ip.valid_ipv4(global_admin):
193         ext_com = BGPIPv4AddressSpecificExtendedCommunity(
194             subtype=subtype,
195             ipv4_address=global_admin,
196             local_administrator=local_admin)
197     else:
198         raise ValueError(
199             'Invalid Route Target or Route Origin value: %s' % value)
200
201     return ext_com
202
203
204 def create_v4flowspec_actions(actions=None):
205     """
206     Create list of traffic filtering actions
207     for Ipv4 Flow Specification and VPNv4 Flow Specification.
208
209     `` actions`` specifies Traffic Filtering Actions of
210     Flow Specification as a dictionary type value.
211
212     Returns a list of extended community values.
213     """
214     from ryu.services.protocols.bgp.api.prefix import (
215         FLOWSPEC_ACTION_TRAFFIC_RATE,
216         FLOWSPEC_ACTION_TRAFFIC_ACTION,
217         FLOWSPEC_ACTION_REDIRECT,
218         FLOWSPEC_ACTION_TRAFFIC_MARKING,
219     )
220
221     # Supported action type for IPv4 and VPNv4.
222     action_types = {
223         FLOWSPEC_ACTION_TRAFFIC_RATE: BGPFlowSpecTrafficRateCommunity,
224         FLOWSPEC_ACTION_TRAFFIC_ACTION: BGPFlowSpecTrafficActionCommunity,
225         FLOWSPEC_ACTION_REDIRECT: BGPFlowSpecRedirectCommunity,
226         FLOWSPEC_ACTION_TRAFFIC_MARKING: BGPFlowSpecTrafficMarkingCommunity,
227     }
228
229     return _create_actions(actions, action_types)
230
231
232 def create_v6flowspec_actions(actions=None):
233     """
234     Create list of traffic filtering actions
235     for Ipv6 Flow Specification and VPNv6 Flow Specification.
236
237     "FLOWSPEC_ACTION_REDIRECT_IPV6" is not implemented yet.
238     """
239     from ryu.services.protocols.bgp.api.prefix import (
240         FLOWSPEC_ACTION_TRAFFIC_RATE,
241         FLOWSPEC_ACTION_TRAFFIC_ACTION,
242         FLOWSPEC_ACTION_REDIRECT,
243         FLOWSPEC_ACTION_TRAFFIC_MARKING,
244     )
245
246     # Supported action type for IPv6 and VPNv6.
247     action_types = {
248         FLOWSPEC_ACTION_TRAFFIC_RATE: BGPFlowSpecTrafficRateCommunity,
249         FLOWSPEC_ACTION_TRAFFIC_ACTION: BGPFlowSpecTrafficActionCommunity,
250         FLOWSPEC_ACTION_REDIRECT: BGPFlowSpecRedirectCommunity,
251         FLOWSPEC_ACTION_TRAFFIC_MARKING: BGPFlowSpecTrafficMarkingCommunity,
252     }
253
254     return _create_actions(actions, action_types)
255
256
257 def create_l2vpnflowspec_actions(actions=None):
258     """
259     Create list of traffic filtering actions for L2VPN Flow Specification.
260     """
261     from ryu.services.protocols.bgp.api.prefix import (
262         FLOWSPEC_ACTION_TRAFFIC_RATE,
263         FLOWSPEC_ACTION_TRAFFIC_ACTION,
264         FLOWSPEC_ACTION_REDIRECT,
265         FLOWSPEC_ACTION_TRAFFIC_MARKING,
266         FLOWSPEC_ACTION_VLAN,
267         FLOWSPEC_ACTION_TPID,
268     )
269
270     # Supported action type for L2VPN.
271     action_types = {
272         FLOWSPEC_ACTION_TRAFFIC_RATE: BGPFlowSpecTrafficRateCommunity,
273         FLOWSPEC_ACTION_TRAFFIC_ACTION: BGPFlowSpecTrafficActionCommunity,
274         FLOWSPEC_ACTION_REDIRECT: BGPFlowSpecRedirectCommunity,
275         FLOWSPEC_ACTION_TRAFFIC_MARKING: BGPFlowSpecTrafficMarkingCommunity,
276         FLOWSPEC_ACTION_VLAN: BGPFlowSpecVlanActionCommunity,
277         FLOWSPEC_ACTION_TPID: BGPFlowSpecTPIDActionCommunity,
278     }
279
280     return _create_actions(actions, action_types)
281
282
283 def _create_actions(actions, action_types):
284     communities = []
285
286     if actions is None:
287         return communities
288
289     for name, action in actions.items():
290         cls_ = action_types.get(name, None)
291         if cls_:
292             communities.append(cls_(**action))
293         else:
294             raise ValueError(
295                 'Unsupported flowspec action %s' % name)
296
297     return communities