summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ryu/services/protocols/bgp/peer.py211
1 files changed, 45 insertions, 166 deletions
diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py
index 4bca6165..224dd8d3 100644
--- a/ryu/services/protocols/bgp/peer.py
+++ b/ryu/services/protocols/bgp/peer.py
@@ -588,14 +588,6 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
"""Construct update message with Outgoing-routes path attribute
appropriately cloned/copied/updated.
"""
- if self._neigh_conf.cap_mbgp_ipv4:
- update = self._construct_bgp4_update(outgoing_route)
- else:
- update = self._construct_mpbgp_update(outgoing_route)
-
- return update
-
- def _construct_bgp4_update(self, outgoing_route):
update = None
path = outgoing_route.path
# Get copy of path's path attributes.
@@ -603,8 +595,14 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
new_pathattr = []
if path.is_withdraw:
- update = BGPUpdate(withdrawn_routes=[path.nlri])
- return update
+ if self._neigh_conf.cap_mbgp_ipv4:
+ update = BGPUpdate(withdrawn_routes=[path.nlri])
+ return update
+ else:
+ mpunreach_attr = BGPPathAttributeMpUnreachNLRI(
+ path.route_family.afi, path.route_family.safi, [path.nlri]
+ )
+ new_pathattr.append(mpunreach_attr)
else:
# Supported and un-supported/unknown attributes.
origin_attr = None
@@ -629,6 +627,15 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
nexthop_attr = BGPPathAttributeNextHop(next_hop)
assert nexthop_attr, 'Missing NEXTHOP mandatory attribute.'
+ if not self._neigh_conf.cap_mbgp_ipv4:
+ # We construct mpreach-nlri attribute.
+ mpnlri_attr = BGPPathAttributeMpReachNLRI(
+ path.route_family.afi,
+ path.route_family.safi,
+ next_hop,
+ nlri_list
+ )
+
# ORIGIN Attribute.
# According to RFC this attribute value SHOULD NOT be changed by
# any other speaker.
@@ -705,12 +712,27 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
if path_extcomm_attr:
# SOO list can be configured per VRF and/or per Neighbor.
# NeighborConf has this setting we add this to existing list.
- soo_list = path_extcomm_attr.soo_list
+ communities = path_extcomm_attr.communities
if self._neigh_conf.soo_list:
- soo_list.extend(self._neigh_conf.soo_list)
+ #construct extended community
+ soo_list = self._neigh_conf.soo_list
+ subtype = 0x03
+ for soo in soo_list:
+ first, second = soo.split(':')
+ if '.' in first:
+ c = BGPIPv4AddressSpecificExtendedCommunity(
+ subtype=subtype,
+ ipv4_address=first,
+ local_administrator=int(second))
+ else:
+ c = BGPTwoOctetAsSpecificExtendedCommunity(
+ subtype=subtype,
+ as_number=int(first),
+ local_administrator=int(second))
+ communities.append(c)
+
extcomm_attr = BGPPathAttributeExtendedCommunities(
- path_extcomm_attr.rt_list,
- soo_list
+ communities=communities
)
# UNKOWN Attributes.
@@ -720,158 +742,11 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
# Ordering path attributes according to type as RFC says. We set
# MPReachNLRI first as advised by experts as a new trend in BGP
# implementation.
- new_pathattr.append(nexthop_attr)
- new_pathattr.append(origin_attr)
- new_pathattr.append(aspath_attr)
- if multi_exit_disc:
- new_pathattr.append(multi_exit_disc)
- if localpref_attr:
- new_pathattr.append(localpref_attr)
- if community_attr:
- new_pathattr.append(community_attr)
- if extcomm_attr:
- new_pathattr.append(extcomm_attr)
- if unkown_opttrans_attrs:
- new_pathattr.extend(unkown_opttrans_attrs.values())
-
- update = BGPUpdate(path_attributes=new_pathattr,
- nlri=nlri_list)
- return update
-
- def _construct_mpbgp_update(self, outgoing_route):
- """Construct update message with Outgoing-routes path attribute
- appropriately cloned/copied/updated.
- """
- # TODO(PH): Investigate how this case needs to be handled for iBGP.
- update = None
- path = outgoing_route.path
- # Get copy of path's path attributes.
- pathattr_map = path.pathattr_map
- new_pathattr = []
-
- # If this is withdraw update we copy MpUnReach path-attribute and
- # create new Update message.
- if path.is_withdraw:
- # MP_UNREACH_NLRI Attribute.
- mpunreach_attr = BGPPathAttributeMpUnreachNLRI(
- path.route_family.afi, path.route_family.safi, [path.nlri]
- )
- new_pathattr.append(mpunreach_attr)
- else:
- # Supported and un-supported/unknown attributes.
- origin_attr = None
- aspath_attr = None
- mpnlri_attr = None
- extcomm_attr = None
- community_attr = None
- localpref_attr = None
- unkown_opttrans_attrs = None
-
- # MP_REACH_NLRI Attribute.
- # By default we use BGPS's interface IP with this peer as next_hop.
- # TODO(PH): change to use protocol's local address.
- # next_hop = self._neigh_conf.host_bind_ip
- next_hop = self._session_next_hop(path.route_family)
- # If this is a iBGP peer.
- if not self.is_ebgp_peer() and path.source is not None:
- # If the path came from a bgp peer and not from NC, according
- # to RFC 4271 we should not modify next_hop.
- next_hop = path.nexthop
- # We construct mpreach-nlri attribute.
- mpnlri_attr = BGPPathAttributeMpReachNLRI(
- path.route_family.afi,
- path.route_family.safi,
- next_hop,
- [path.nlri]
- )
-
- # ORIGIN Attribute.
- # According to RFC this attribute value SHOULD NOT be changed by
- # any other speaker.
- origin_attr = pathattr_map.get(BGP_ATTR_TYPE_ORIGIN)
- assert origin_attr, 'Missing ORIGIN mandatory attribute.'
-
- # AS_PATH Attribute.
- # Construct AS-path-attr using paths aspath attr. with local AS as
- # first item.
- path_aspath = pathattr_map.get(BGP_ATTR_TYPE_AS_PATH)
- assert path_aspath, 'Missing AS_PATH mandatory attribute.'
- # Deep copy aspath_attr value
- path_seg_list = path_aspath.path_seg_list
- # If this is a iBGP peer.
- if not self.is_ebgp_peer():
- # When a given BGP speaker advertises the route to an internal
- # peer, the advertising speaker SHALL NOT modify the AS_PATH
- # attribute associated with the route.
- aspath_attr = BGPPathAttributeAsPath(path_seg_list)
+ if self._neigh_conf.cap_mbgp_ipv4:
+ new_pathattr.append(nexthop_attr)
else:
- # When a given BGP speaker advertises the route to an external
- # peer, the advertising speaker updates the AS_PATH attribute
- # as follows:
- # 1) if the first path segment of the AS_PATH is of type
- # AS_SEQUENCE, the local system prepends its own AS num as
- # the last element of the sequence (put it in the left-most
- # position with respect to the position of octets in the
- # protocol message). If the act of prepending will cause an
- # overflow in the AS_PATH segment (i.e., more than 255
- # ASes), it SHOULD prepend a new segment of type AS_SEQUENCE
- # and prepend its own AS number to this new segment.
- #
- # 2) if the first path segment of the AS_PATH is of type AS_SET
- # , the local system prepends a new path segment of type
- # AS_SEQUENCE to the AS_PATH, including its own AS number in
- # that segment.
- #
- # 3) if the AS_PATH is empty, the local system creates a path
- # segment of type AS_SEQUENCE, places its own AS into that
- # segment, and places that segment into the AS_PATH.
- if (len(path_seg_list) > 0 and
- isinstance(path_seg_list[0], list) and
- len(path_seg_list[0]) < 255):
- path_seg_list[0].insert(0, self._core_service.asn)
- else:
- path_seg_list.insert(0, [self._core_service.asn])
- aspath_attr = BGPPathAttributeAsPath(path_seg_list)
-
- # MULTI_EXIT_DISC Attribute.
- # For eBGP session we can send multi-exit-disc if configured.
- multi_exit_disc = None
- if self.is_ebgp_peer():
- multi_exit_disc = pathattr_map.get(
- BGP_ATTR_TYPE_MULTI_EXIT_DISC)
-
- # LOCAL_PREF Attribute.
- if not self.is_ebgp_peer():
- # For iBGP peers we are required to send local-pref attribute
- # for connected or local prefixes. We send default local-pref.
- localpref_attr = pathattr.LocalPref(100)
+ new_pathattr.append(mpnlri_attr)
- # COMMUNITY Attribute.
- community_attr = pathattr_map.get(BGP_ATTR_TYPE_COMMUNITIES)
-
- # EXTENDED COMMUNITY Attribute.
- # Construct ExtCommunity path-attr based on given.
- path_extcomm_attr = pathattr_map.get(
- BGP_ATTR_TYPE_EXTENDED_COMMUNITIES
- )
- if path_extcomm_attr:
- # SOO list can be configured per VRF and/or per Neighbor.
- # NeighborConf has this setting we add this to existing list.
- soo_list = path_extcomm_attr.soo_list
- if self._neigh_conf.soo_list:
- soo_list.extend(self._neigh_conf.soo_list)
- extcomm_attr = BGPPathAttributeExtendedCommunities(
- path_extcomm_attr.rt_list+soo_list
- )
-
- # UNKOWN Attributes.
- # Get optional transitive path attributes
- unkown_opttrans_attrs = bgp_utils.get_unknow_opttrans_attr(path)
-
- # Ordering path attributes according to type as RFC says. We set
- # MPReachNLRI first as advised by experts as a new trend in BGP
- # implementation.
- new_pathattr.append(mpnlri_attr)
new_pathattr.append(origin_attr)
new_pathattr.append(aspath_attr)
if multi_exit_disc:
@@ -885,8 +760,12 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
if unkown_opttrans_attrs:
new_pathattr.extend(unkown_opttrans_attrs.values())
- update = BGPUpdate(path_attributes=new_pathattr)
- return update
+ if self._neigh_conf.cap_mbgp_ipv4:
+ update = BGPUpdate(path_attributes=new_pathattr,
+ nlri=nlri_list)
+ else:
+ update = BGPUpdate(path_attributes=new_pathattr)
+ return update
def _connect_loop(self, client_factory):
"""In the current greeenlet we try to establish connection with peer.