mirror of
https://github.com/faucetsdn/ryu.git
synced 2026-05-06 04:46:10 +02:00
bgp: support next_hop_self
Support next_hop_self. BGPSpeaker can replace a path's next_hop address with its own address when it sends the path to iBGP peer. Signed-off-by: Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
dca514f198
commit
75753841aa
@ -57,6 +57,7 @@ from ryu.services.protocols.bgp.rtconf.neighbors import PASSWORD
|
||||
from ryu.services.protocols.bgp.rtconf.neighbors import IN_FILTER
|
||||
from ryu.services.protocols.bgp.rtconf.neighbors import OUT_FILTER
|
||||
from ryu.services.protocols.bgp.rtconf.neighbors import IS_ROUTE_SERVER_CLIENT
|
||||
from ryu.services.protocols.bgp.rtconf.neighbors import IS_NEXT_HOP_SELF
|
||||
from ryu.services.protocols.bgp.info_base.base import Filter
|
||||
|
||||
|
||||
@ -179,7 +180,8 @@ class BGPSpeaker(object):
|
||||
enable_vpnv4=DEFAULT_CAP_MBGP_VPNV4,
|
||||
enable_vpnv6=DEFAULT_CAP_MBGP_VPNV6,
|
||||
next_hop=None, password=None, multi_exit_disc=None,
|
||||
site_of_origins=None, is_route_server_client=False):
|
||||
site_of_origins=None, is_route_server_client=False,
|
||||
is_next_hop_self=False):
|
||||
""" This method registers a new neighbor. The BGP speaker tries to
|
||||
establish a bgp session with the peer (accepts a connection
|
||||
from the peer and also tries to connect to it).
|
||||
@ -215,6 +217,9 @@ class BGPSpeaker(object):
|
||||
|
||||
``is_route_server_client`` specifies whether this neighbor is a
|
||||
router server's client or not.
|
||||
|
||||
``is_next_hop_self`` specifies whether the BGP speaker announces
|
||||
its own ip address to iBGP neighbor or not as path's next_hop address.
|
||||
"""
|
||||
bgp_neighbor = {}
|
||||
bgp_neighbor[neighbors.IP_ADDRESS] = address
|
||||
@ -222,6 +227,7 @@ class BGPSpeaker(object):
|
||||
bgp_neighbor[PEER_NEXT_HOP] = next_hop
|
||||
bgp_neighbor[PASSWORD] = password
|
||||
bgp_neighbor[IS_ROUTE_SERVER_CLIENT] = is_route_server_client
|
||||
bgp_neighbor[IS_NEXT_HOP_SELF] = is_next_hop_self
|
||||
# v6 advertizement is available with only v6 peering
|
||||
if netaddr.valid_ipv4(address):
|
||||
bgp_neighbor[CAP_MBGP_IPV4] = enable_ipv4
|
||||
|
||||
@ -783,15 +783,16 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
else:
|
||||
next_hop = self.host_bind_ip
|
||||
if route_family == RF_IPv6_VPN:
|
||||
# Next hop ipv4_mapped ipv6
|
||||
def _ipv4_mapped_ipv6(ipv4):
|
||||
from netaddr import IPAddress
|
||||
return str(IPAddress(ipv4).ipv6())
|
||||
|
||||
next_hop = _ipv4_mapped_ipv6(next_hop)
|
||||
next_hop = self._ipv4_mapped_ipv6(next_hop)
|
||||
|
||||
return next_hop
|
||||
|
||||
@staticmethod
|
||||
def _ipv4_mapped_ipv6(ipv4_address):
|
||||
# Next hop ipv4_mapped ipv6
|
||||
from netaddr import IPAddress
|
||||
return str(IPAddress(ipv4_address).ipv6())
|
||||
|
||||
def _construct_update(self, outgoing_route):
|
||||
"""Construct update message with Outgoing-routes path attribute
|
||||
appropriately cloned/copied/updated.
|
||||
@ -835,7 +836,17 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
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
|
||||
# However RFC 4271 allows us to change next_hop
|
||||
# if configured to announce its own ip address.
|
||||
if self._neigh_conf.is_next_hop_self:
|
||||
next_hop = self.host_bind_ip
|
||||
if path.route_family == RF_IPv6_VPN:
|
||||
next_hop = self._ipv4_mapped_ipv6(next_hop)
|
||||
LOG.debug('using %s as a next_hop address instead'
|
||||
' of path.nexthop %s' % (next_hop, path.nexthop))
|
||||
else:
|
||||
next_hop = path.nexthop
|
||||
|
||||
nexthop_attr = BGPPathAttributeNextHop(next_hop)
|
||||
assert nexthop_attr, 'Missing NEXTHOP mandatory attribute.'
|
||||
|
||||
|
||||
@ -81,6 +81,7 @@ OUT_FILTER = 'out_filter'
|
||||
IS_ROUTE_SERVER_CLIENT = 'is_route_server_client'
|
||||
CHECK_FIRST_AS = 'check_first_as'
|
||||
ATTRIBUTE_MAP = 'attribute_map'
|
||||
IS_NEXT_HOP_SELF = 'is_next_hop_self'
|
||||
|
||||
# Default value constants.
|
||||
DEFAULT_CAP_GR_NULL = True
|
||||
@ -97,6 +98,7 @@ DEFAULT_IN_FILTER = []
|
||||
DEFAULT_OUT_FILTER = []
|
||||
DEFAULT_IS_ROUTE_SERVER_CLIENT = False
|
||||
DEFAULT_CHECK_FIRST_AS = False
|
||||
DEFAULT_IS_NEXT_HOP_SELF = False
|
||||
|
||||
# Default value for *MAX_PREFIXES* setting is set to 0.
|
||||
DEFAULT_MAX_PREFIXES = 0
|
||||
@ -255,6 +257,15 @@ def validate_check_first_as(check_first_as):
|
||||
return check_first_as
|
||||
|
||||
|
||||
@validate(name=IS_NEXT_HOP_SELF)
|
||||
def validate_is_next_hop_self(is_next_hop_self):
|
||||
if is_next_hop_self not in (True, False):
|
||||
raise ConfigValueError(desc='Invalid is_next_hop_self(%s)' %
|
||||
is_next_hop_self)
|
||||
|
||||
return is_next_hop_self
|
||||
|
||||
|
||||
class NeighborConf(ConfWithId, ConfWithStats):
|
||||
"""Class that encapsulates one neighbors' configuration."""
|
||||
|
||||
@ -273,7 +284,8 @@ class NeighborConf(ConfWithId, ConfWithStats):
|
||||
LOCAL_ADDRESS, LOCAL_PORT,
|
||||
PEER_NEXT_HOP, PASSWORD,
|
||||
IN_FILTER, OUT_FILTER,
|
||||
IS_ROUTE_SERVER_CLIENT, CHECK_FIRST_AS])
|
||||
IS_ROUTE_SERVER_CLIENT, CHECK_FIRST_AS,
|
||||
IS_NEXT_HOP_SELF])
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(NeighborConf, self).__init__(**kwargs)
|
||||
@ -308,6 +320,9 @@ class NeighborConf(ConfWithId, ConfWithStats):
|
||||
DEFAULT_IS_ROUTE_SERVER_CLIENT, **kwargs)
|
||||
self._settings[CHECK_FIRST_AS] = compute_optional_conf(
|
||||
CHECK_FIRST_AS, DEFAULT_CHECK_FIRST_AS, **kwargs)
|
||||
self._settings[IS_NEXT_HOP_SELF] = compute_optional_conf(
|
||||
IS_NEXT_HOP_SELF,
|
||||
DEFAULT_IS_NEXT_HOP_SELF, **kwargs)
|
||||
|
||||
# We do not have valid default MED value.
|
||||
# If no MED attribute is provided then we do not have to use MED.
|
||||
@ -490,6 +505,10 @@ class NeighborConf(ConfWithId, ConfWithStats):
|
||||
def check_first_as(self):
|
||||
return self._settings[CHECK_FIRST_AS]
|
||||
|
||||
@property
|
||||
def is_next_hop_self(self):
|
||||
return self._settings[IS_NEXT_HOP_SELF]
|
||||
|
||||
def exceeds_max_prefix_allowed(self, prefix_count):
|
||||
allowed_max = self._settings[MAX_PREFIXES]
|
||||
does_exceed = False
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user