summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2014-03-30 08:45:03 +0000
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2014-04-01 17:29:15 +0900
commit06c84f4b05f1e77e5d3bf0446af043532edae430 (patch)
tree4bf66a92b1373b2192a15f73dc48ecefd3b13ce8
parent706cd11ce38093263e0e43792aef64ed60535395 (diff)
bgp: send BGP UPDATE msg in BGP4 format when nlri is ipv4
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/services/protocols/bgp/model.py7
-rw-r--r--ryu/services/protocols/bgp/peer.py164
2 files changed, 167 insertions, 4 deletions
diff --git a/ryu/services/protocols/bgp/model.py b/ryu/services/protocols/bgp/model.py
index ebc779d4..d8da7384 100644
--- a/ryu/services/protocols/bgp/model.py
+++ b/ryu/services/protocols/bgp/model.py
@@ -44,11 +44,11 @@ class OutgoingRoute(object):
"""Holds state about a route that is queued for being sent to a given sink.
"""
- __slots__ = ('_path', '_for_route_refresh',
+ __slots__ = ('_path', '_for_route_refresh', 'bgp4_format',
'sink', 'next_outgoing_route', 'prev_outgoing_route',
'next_sink_out_route', 'prev_sink_out_route')
- def __init__(self, path, for_route_refresh=False):
+ def __init__(self, path, for_route_refresh=False, bgp4_format=False):
assert(path)
self.sink = None
@@ -59,6 +59,9 @@ class OutgoingRoute(object):
# No sent-route is queued for the destination for this update.
self._for_route_refresh = for_route_refresh
+ # Construct UPDATE msg using bgp4 format
+ self.bgp4_format = bgp4_format
+
# Automatically generated, for list off of Destination.
#
# self.next_outgoing_route
diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py
index 2b41b62c..5dd1c83f 100644
--- a/ryu/services/protocols/bgp/peer.py
+++ b/ryu/services/protocols/bgp/peer.py
@@ -556,6 +556,160 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
"""Construct update message with Outgoing-routes path attribute
appropriately cloned/copied/updated.
"""
+ is_bgp4_format = outgoing_route.bgp4_format
+ if is_bgp4_format:
+ 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.
+ pathattr_map = path.pathattr_map
+ new_pathattr_map = OrderedDict()
+
+ if path.is_withdraw:
+ update = messages.Update(withdraw_list=path.nlri)
+ return update
+ else:
+ # Supported and un-supported/unknown attributes.
+ origin_attr = None
+ nexthop_attr = None
+ aspath_attr = None
+ extcomm_attr = None
+ community_attr = None
+ localpref_attr = None
+ unkown_opttrans_attrs = None
+ nlri_list = [path.nlri]
+
+ # 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
+ nexthop_attr = pathattr.NextHop(next_hop)
+ assert nexthop_attr, 'Missing NEXTHOP mandatory attribute.'
+
+ # ORIGIN Attribute.
+ # According to RFC this attribute value SHOULD NOT be changed by
+ # any other speaker.
+ origin_attr = pathattr_map.get(pathattr.Origin.ATTR_NAME)
+ 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(pathattr.AsPath.ATTR_NAME)
+ 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 = pathattr.AsPath(path_seg_list)
+ 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 = pathattr.AsPath(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(pathattr.Med.ATTR_NAME)
+ if not multi_exit_disc and self._neigh_conf.multi_exit_disc:
+ multi_exit_disc = pathattr.Med(
+ self._neigh_conf.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)
+
+ # COMMUNITY Attribute.
+ community_attr = pathattr_map.get(pathattr.Community.ATTR_NAME)
+
+ # EXTENDED COMMUNITY Attribute.
+ # Construct ExtCommunity path-attr based on given.
+ path_extcomm_attr = pathattr_map.get(
+ pathattr.ExtCommunity.ATTR_NAME
+ )
+ 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 = pathattr.ExtCommunity(
+ 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_map[pathattr.NextHop.ATTR_NAME] = nexthop_attr
+ new_pathattr_map[pathattr.Origin.ATTR_NAME] = origin_attr
+ new_pathattr_map[pathattr.AsPath.ATTR_NAME] = aspath_attr
+ if multi_exit_disc:
+ new_pathattr_map[pathattr.Med.ATTR_NAME] = multi_exit_disc
+ if localpref_attr:
+ new_pathattr_map[pathattr.LocalPref.ATTR_NAME] = localpref_attr
+ if community_attr:
+ new_pathattr_map[pathattr.Community.ATTR_NAME] = community_attr
+ if extcomm_attr:
+ new_pathattr_map[pathattr.ExtCommunity.ATTR_NAME] =\
+ extcomm_attr
+ if unkown_opttrans_attrs:
+ new_pathattr_map.update(unkown_opttrans_attrs)
+ update = messages.Update(pathattr_map=new_pathattr_map,
+ nlri_list=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
@@ -1519,7 +1673,10 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
if path.source is None:
# Construct OutgoingRoute specific for this peer and put it in
# its sink.
- outgoing_route = OutgoingRoute(path)
+ bgp4_format = False
+ if self._neigh_conf.cap_mbgp_ipv4:
+ bgp4_format = True
+ outgoing_route = OutgoingRoute(path, bgp4_format=bgp4_format)
self.enque_outgoing_msg(outgoing_route)
# If path from a bgp-peer is new best path, we share it with
@@ -1568,7 +1725,10 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
# Construct OutgoingRoute specific for this peer and put it in
# its sink.
- outgoing_route = OutgoingRoute(path)
+ bgp4_format = False
+ if self._neigh_conf.cap_mbgp_ipv4:
+ bgp4_format = True
+ outgoing_route = OutgoingRoute(path, bgp4_format=bgp4_format)
self.enque_outgoing_msg(outgoing_route)
LOG.debug('Enqueued outgoing route %s for peer %s' %
(outgoing_route.path.nlri, self))