1 # Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
17 Utilities related to bgp data types and models.
23 from ryu.lib import ip
24 from ryu.lib.packet.bgp import (
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,
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
69 LOG = logging.getLogger('utils.bgp')
71 # RouteFamily to path sub-class mapping.
72 _ROUTE_FAMILY_TO_PATH_MAP = {RF_IPv4_UC: Ipv4Path,
74 RF_IPv4_VPN: Vpnv4Path,
75 RF_IPv6_VPN: Vpnv6Path,
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,
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)
92 def clone_path_and_update_med_for_target_neighbor(path, 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' %
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)
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
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.
113 - `path`: (Path) RT_NLRI path
114 - `new_rt_as`: AS value of cloned paths' RT_NLRI
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')
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)
126 def from_inet_ptoi(bgp_id):
127 """Convert an IPv4 address string format to a four byte long.
131 four_byte_id = ip.ipv4_to_int(bgp_id)
133 LOG.debug('Invalid bgp id given for conversion to integer value %s',
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`.
143 Returns dict: <key> - attribute type code, <value> - unknown path-attr.
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
155 return unknown_opt_tran_attrs
158 def create_end_of_rib_update():
159 """Construct end-of-rib (EOR) Update instance."""
160 mpunreach_attr = BGPPathAttributeMpUnreachNLRI(RF_IPv4_VPN.afi,
163 eor = BGPUpdate(path_attributes=[mpunreach_attr])
167 # Bgp update message instance that can used as End of RIB marker.
168 UPDATE_EOR = create_end_of_rib_update()
171 def create_rt_extended_community(value, subtype=2):
173 Creates an instance of the BGP Route Target Community (if "subtype=2")
174 or Route Origin Community ("subtype=3").
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.
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(
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(
190 as_number=int(global_admin),
191 local_administrator=local_admin)
192 elif ip.valid_ipv4(global_admin):
193 ext_com = BGPIPv4AddressSpecificExtendedCommunity(
195 ipv4_address=global_admin,
196 local_administrator=local_admin)
199 'Invalid Route Target or Route Origin value: %s' % value)
204 def create_v4flowspec_actions(actions=None):
206 Create list of traffic filtering actions
207 for Ipv4 Flow Specification and VPNv4 Flow Specification.
209 `` actions`` specifies Traffic Filtering Actions of
210 Flow Specification as a dictionary type value.
212 Returns a list of extended community values.
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,
221 # Supported action type for IPv4 and VPNv4.
223 FLOWSPEC_ACTION_TRAFFIC_RATE: BGPFlowSpecTrafficRateCommunity,
224 FLOWSPEC_ACTION_TRAFFIC_ACTION: BGPFlowSpecTrafficActionCommunity,
225 FLOWSPEC_ACTION_REDIRECT: BGPFlowSpecRedirectCommunity,
226 FLOWSPEC_ACTION_TRAFFIC_MARKING: BGPFlowSpecTrafficMarkingCommunity,
229 return _create_actions(actions, action_types)
232 def create_v6flowspec_actions(actions=None):
234 Create list of traffic filtering actions
235 for Ipv6 Flow Specification and VPNv6 Flow Specification.
237 "FLOWSPEC_ACTION_REDIRECT_IPV6" is not implemented yet.
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,
246 # Supported action type for IPv6 and VPNv6.
248 FLOWSPEC_ACTION_TRAFFIC_RATE: BGPFlowSpecTrafficRateCommunity,
249 FLOWSPEC_ACTION_TRAFFIC_ACTION: BGPFlowSpecTrafficActionCommunity,
250 FLOWSPEC_ACTION_REDIRECT: BGPFlowSpecRedirectCommunity,
251 FLOWSPEC_ACTION_TRAFFIC_MARKING: BGPFlowSpecTrafficMarkingCommunity,
254 return _create_actions(actions, action_types)
257 def create_l2vpnflowspec_actions(actions=None):
259 Create list of traffic filtering actions for L2VPN Flow Specification.
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,
270 # Supported action type for L2VPN.
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,
280 return _create_actions(actions, action_types)
283 def _create_actions(actions, action_types):
289 for name, action in actions.items():
290 cls_ = action_types.get(name, None)
292 communities.append(cls_(**action))
295 'Unsupported flowspec action %s' % name)