mirror of
https://github.com/faucetsdn/ryu.git
synced 2026-01-25 02:21:45 +01:00
bgp: use ryu bgp packet library instead of original one
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
bdad6267de
commit
9d5e66fa4e
@ -79,9 +79,9 @@ def reset_neighor(ip_address):
|
||||
return True
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
# Common configuration related APIs
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
|
||||
@register(name='comm_conf.get')
|
||||
def get_common_conf():
|
||||
|
||||
@ -33,9 +33,9 @@ from ryu.services.protocols.bgp.rtconf.vrfs import VrfConf
|
||||
LOG = logging.getLogger('bgpspeaker.api.rtconf')
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
# Neighbor configuration related APIs
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
|
||||
|
||||
def _get_neighbor_conf(neigh_ip_address):
|
||||
@ -112,9 +112,9 @@ def get_neighbors_conf():
|
||||
return CORE_MANAGER.neighbors_conf.settings
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
# VRF configuration related APIs
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
|
||||
@register(name='vrf.create')
|
||||
def create_vrf(**kwargs):
|
||||
@ -168,9 +168,9 @@ def get_vrfs_conf():
|
||||
vrfs_conf = CORE_MANAGER.vrfs_conf
|
||||
return vrfs_conf.settings
|
||||
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
# network configuration related APIs
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
|
||||
|
||||
@register(name='network.add')
|
||||
|
||||
@ -23,7 +23,11 @@ import traceback
|
||||
import weakref
|
||||
|
||||
from eventlet.timeout import Timeout
|
||||
from ryu.services.protocols.bgp.protocols.bgp import nlri
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv6_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
from ryu.services.protocols.bgp.utils.circlist import CircularListType
|
||||
from ryu.services.protocols.bgp.utils.evtlet import LoopingCall
|
||||
|
||||
@ -42,10 +46,10 @@ OrderedDict = OrderedDict
|
||||
|
||||
|
||||
# Currently supported address families.
|
||||
SUPPORTED_GLOBAL_RF = set([nlri.RF_IPv4_UC,
|
||||
nlri.RF_IPv4_VPN,
|
||||
nlri.RF_RTC_UC,
|
||||
nlri.RF_IPv6_VPN
|
||||
SUPPORTED_GLOBAL_RF = set([RF_IPv4_UC,
|
||||
RF_IPv4_VPN,
|
||||
RF_RTC_UC,
|
||||
RF_IPv6_VPN
|
||||
])
|
||||
|
||||
|
||||
|
||||
@ -21,9 +21,12 @@
|
||||
"""
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp import exceptions
|
||||
from ryu.services.protocols.bgp.protocols.bgp import nlri
|
||||
from ryu.services.protocols.bgp.protocols.bgp import pathattr
|
||||
from ryu.lib.packet.bgp import BGP_ERROR_CEASE
|
||||
from ryu.lib.packet.bgp import BGP_ERROR_SUB_CONNECTION_RESET
|
||||
from ryu.lib.packet.bgp import BGP_ERROR_SUB_CONNECTION_COLLISION_RESOLUTION
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_INCOMPLETE
|
||||
|
||||
from ryu.services.protocols.bgp.base import Activity
|
||||
from ryu.services.protocols.bgp.base import add_bgp_error_metadata
|
||||
from ryu.services.protocols.bgp.base import BGPSException
|
||||
@ -45,7 +48,7 @@ LOG = logging.getLogger('bgpspeaker.core')
|
||||
CORE_IP = '0.0.0.0'
|
||||
|
||||
# Required dictates that Origin attribute be incomplete
|
||||
EXPECTED_ORIGIN = pathattr.Origin.INCOMPLETE
|
||||
EXPECTED_ORIGIN = BGP_ATTR_ORIGIN_INCOMPLETE
|
||||
|
||||
|
||||
@add_bgp_error_metadata(code=CORE_ERROR_CODE, sub_code=1,
|
||||
@ -222,9 +225,9 @@ class CoreService(Factory, Activity):
|
||||
server_thread.wait()
|
||||
processor_thread.wait()
|
||||
|
||||
#=========================================================================
|
||||
# ========================================================================
|
||||
# RTC address family related utilities
|
||||
#=========================================================================
|
||||
# ========================================================================
|
||||
|
||||
def update_rtfilters(self):
|
||||
"""Updates RT filters for each peer.
|
||||
@ -271,7 +274,7 @@ class CoreService(Factory, Activity):
|
||||
- `old_rts`: (set) of RTs that peers is no longer interested in.
|
||||
"""
|
||||
for table in self._table_manager._global_tables.itervalues():
|
||||
if table.route_family == nlri.RF_RTC_UC:
|
||||
if table.route_family == RF_RTC_UC:
|
||||
continue
|
||||
self._spawn('rt_filter_chg_%s' % peer,
|
||||
self._rt_mgr.on_rt_filter_chg_sync_peer,
|
||||
@ -340,9 +343,9 @@ class CoreService(Factory, Activity):
|
||||
|
||||
return rtfilter_map
|
||||
|
||||
#=========================================================================
|
||||
# ========================================================================
|
||||
# Peer or Neighbor related handles/utilities.
|
||||
#=========================================================================
|
||||
# ========================================================================
|
||||
def register_flexinet_sink(self, sink):
|
||||
self._sinks.add(sink)
|
||||
|
||||
@ -408,8 +411,8 @@ class CoreService(Factory, Activity):
|
||||
LOG.debug('Closed connection to %s:%s as it is not a recognized'
|
||||
' peer.' % (peer_addr, peer_port))
|
||||
# Send connection rejected notification as per RFC
|
||||
code = exceptions.ConnRejected.CODE
|
||||
subcode = exceptions.ConnRejected.SUB_CODE
|
||||
code = BGP_ERROR_CEASE
|
||||
subcode = BGP_ERROR_SUB_CONNECTION_RESET
|
||||
bgp_proto.send_notification(code, subcode)
|
||||
elif not (peer.in_idle() or peer.in_active() or peer.in_connect()):
|
||||
LOG.debug('Closing connection to %s:%s as we have connection'
|
||||
@ -417,8 +420,8 @@ class CoreService(Factory, Activity):
|
||||
' i.e. connection resolution' %
|
||||
(peer_addr, peer_port))
|
||||
# Send Connection Collision Resolution notification as per RFC.
|
||||
code = exceptions.CollisionResolution.CODE
|
||||
subcode = exceptions.CollisionResolution.SUB_CODE
|
||||
code = BGP_ERROR_CEASE
|
||||
subcode = BGP_ERROR_SUB_CONNECTION_COLLISION_RESOLUTION
|
||||
bgp_proto.send_notification(code, subcode)
|
||||
else:
|
||||
self._spawn_activity(bgp_proto, peer)
|
||||
|
||||
@ -3,11 +3,15 @@ import logging
|
||||
from ryu.services.protocols.bgp.base import SUPPORTED_GLOBAL_RF
|
||||
from ryu.services.protocols.bgp.model import OutgoingRoute
|
||||
from ryu.services.protocols.bgp.peer import Peer
|
||||
from ryu.services.protocols.bgp.protocols.bgp import pathattr
|
||||
from ryu.services.protocols.bgp.protocols.bgp import nlri
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MULTI_EXIT_DISC
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_COMMUNITIES
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv6_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
from ryu.services.protocols.bgp.utils.bgp \
|
||||
import clone_path_and_update_med_for_target_neighbor
|
||||
|
||||
LOG = logging.getLogger('bgpspeaker.core_managers.peer_manager')
|
||||
|
||||
|
||||
@ -64,7 +68,7 @@ class PeerManager(object):
|
||||
non_rtc_peer_list = set()
|
||||
for peer in self._peers.itervalues():
|
||||
if (peer.in_established() and
|
||||
not peer.is_mpbgp_cap_valid(nlri.RF_RTC_UC)):
|
||||
not peer.is_mpbgp_cap_valid(RF_RTC_UC)):
|
||||
non_rtc_peer_list.add(peer)
|
||||
return non_rtc_peer_list
|
||||
|
||||
@ -115,8 +119,8 @@ class PeerManager(object):
|
||||
# wasn't set at all now it could have changed and we may
|
||||
# need to set new value there
|
||||
p = sent_route.path
|
||||
if p.med_set_by_target_neighbor\
|
||||
or p.get_pattr(pathattr.Med.ATTR_NAME) is None:
|
||||
if p.med_set_by_target_neighbor or p.get_pattr(
|
||||
BGP_ATTR_TYPE_MULTI_EXIT_DISC) is None:
|
||||
sent_route.path = \
|
||||
clone_path_and_update_med_for_target_neighbor(
|
||||
sent_route.path, peer.med
|
||||
@ -131,7 +135,7 @@ class PeerManager(object):
|
||||
|
||||
Skips making request to peer that have valid RTC capability.
|
||||
"""
|
||||
assert route_family != nlri.RF_RTC_UC
|
||||
assert route_family != RF_RTC_UC
|
||||
for peer in self._peers.itervalues():
|
||||
# First check if peer is in established state
|
||||
if (peer.in_established and
|
||||
@ -139,7 +143,7 @@ class PeerManager(object):
|
||||
# family
|
||||
peer.is_mbgp_cap_valid(route_family) and
|
||||
# Check if peer has valid capability for RTC
|
||||
not peer.is_mbgp_cap_valid(nlri.RF_RTC_UC)):
|
||||
not peer.is_mbgp_cap_valid(RF_RTC_UC)):
|
||||
peer.request_route_refresh(route_family)
|
||||
|
||||
def make_route_refresh_request(self, peer_ip, *route_families):
|
||||
@ -185,7 +189,7 @@ class PeerManager(object):
|
||||
match this setting.
|
||||
"""
|
||||
# First check if for this peer mpbgp-rtc is valid.
|
||||
if not peer.is_mbgp_cap_valid(nlri.RF_RTC_UC):
|
||||
if not peer.is_mbgp_cap_valid(RF_RTC_UC):
|
||||
return
|
||||
|
||||
neigh_conf = self._neighbors_conf.get_neighbor_conf(peer.ip_address)
|
||||
@ -209,7 +213,7 @@ class PeerManager(object):
|
||||
peer.communicate_path(best_path)
|
||||
|
||||
# Also communicate EOR as per RFC
|
||||
peer.enque_end_of_rib(nlri.RF_RTC_UC)
|
||||
peer.enque_end_of_rib(RF_RTC_UC)
|
||||
|
||||
def comm_all_best_paths(self, peer):
|
||||
"""Shares/communicates current best paths with this peers.
|
||||
@ -221,7 +225,7 @@ class PeerManager(object):
|
||||
' 1/132')
|
||||
# We will enqueue best path from all global destination.
|
||||
for route_family, table in self._table_manager.iter:
|
||||
if route_family == nlri.RF_RTC_UC:
|
||||
if route_family == RF_RTC_UC:
|
||||
continue
|
||||
if peer.is_mbgp_cap_valid(route_family):
|
||||
for dest in table.itervalues():
|
||||
@ -240,10 +244,10 @@ class PeerManager(object):
|
||||
# Filter based on standard community
|
||||
# If new best path has community attribute, it should be taken into
|
||||
# account when sending UPDATE to peers.
|
||||
comm_attr = new_best_path.get_pattr(pathattr.Community.ATTR_NAME)
|
||||
comm_attr = new_best_path.get_pattr(BGP_ATTR_TYPE_COMMUNITIES)
|
||||
if comm_attr:
|
||||
comm_attr_na = comm_attr.has_comm_attr(
|
||||
pathattr.Community.NO_ADVERTISE
|
||||
BGPPathAttributeCommunities.NO_ADVERTISE
|
||||
)
|
||||
# If we have NO_ADVERTISE attribute is present, we do not send
|
||||
# UPDATE to any peers
|
||||
@ -277,7 +281,7 @@ class PeerManager(object):
|
||||
if path_rts:
|
||||
# We add Default_RTC_NLRI to path RTs so that we can send it to
|
||||
# peers that have expressed interest in all paths
|
||||
path_rts.append(nlri.RtNlri.DEFAULT_RT)
|
||||
path_rts.append(RouteTargetMembershipNLRI.DEFAULT_RT)
|
||||
# All peers that do not have RTC capability qualify
|
||||
qualified_peers = set(self._get_non_rtc_peers())
|
||||
# Peers that have RTC capability and have common RT with the path
|
||||
@ -299,7 +303,7 @@ class PeerManager(object):
|
||||
for route_family in SUPPORTED_GLOBAL_RF:
|
||||
# Since we are dealing with peers that do not support RTC,
|
||||
# ignore this address family
|
||||
if route_family == nlri.RF_RTC_UC:
|
||||
if route_family == RF_RTC_UC:
|
||||
continue
|
||||
|
||||
self.req_rr_to_non_rtc_peers(route_family)
|
||||
|
||||
@ -14,8 +14,21 @@ from ryu.services.protocols.bgp.info_base.vrf6 import Vrf6Table
|
||||
from ryu.services.protocols.bgp.rtconf import vrfs
|
||||
from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4
|
||||
from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV6
|
||||
from ryu.services.protocols.bgp.protocols.bgp import pathattr
|
||||
from ryu.services.protocols.bgp.protocols.bgp import nlri
|
||||
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv6_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeNextHop
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeOrigin
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeAsPath
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_IGP
|
||||
from ryu.lib.packet.bgp import IPAddrPrefix
|
||||
from ryu.lib.packet.bgp import IP6AddrPrefix
|
||||
|
||||
from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4
|
||||
from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4_prefix
|
||||
from ryu.services.protocols.bgp.utils.validation import is_valid_ipv6
|
||||
@ -150,16 +163,16 @@ class TableCoreManager(object):
|
||||
)
|
||||
|
||||
global_table = None
|
||||
if route_family == nlri.RF_IPv4_UC:
|
||||
if route_family == RF_IPv4_UC:
|
||||
global_table = self.get_ipv4_table()
|
||||
|
||||
elif route_family == nlri.RF_IPv4_VPN:
|
||||
elif route_family == RF_IPv4_VPN:
|
||||
global_table = self.get_vpn4_table()
|
||||
|
||||
elif route_family == nlri.RF_IPv6_VPN:
|
||||
elif route_family == RF_IPv6_VPN:
|
||||
global_table = self.get_vpn6_table()
|
||||
|
||||
elif route_family == nlri.RF_RTC_UC:
|
||||
elif route_family == RF_RTC_UC:
|
||||
global_table = self.get_rtc_table()
|
||||
|
||||
return global_table
|
||||
@ -184,12 +197,12 @@ class TableCoreManager(object):
|
||||
Creates the table if it does not exist.
|
||||
"""
|
||||
|
||||
vpn_table = self._global_tables.get(nlri.RF_IPv4_UC)
|
||||
vpn_table = self._global_tables.get(RF_IPv4_UC)
|
||||
# Lazy initialize the table.
|
||||
if not vpn_table:
|
||||
vpn_table = Ipv4Table(self._core_service, self._signal_bus)
|
||||
self._global_tables[nlri.RF_IPv4_UC] = vpn_table
|
||||
self._tables[(None, nlri.RF_IPv4_UC)] = vpn_table
|
||||
self._global_tables[RF_IPv4_UC] = vpn_table
|
||||
self._tables[(None, RF_IPv4_UC)] = vpn_table
|
||||
|
||||
return vpn_table
|
||||
|
||||
@ -198,12 +211,12 @@ class TableCoreManager(object):
|
||||
|
||||
Creates the table if it does not exist.
|
||||
"""
|
||||
vpn_table = self._global_tables.get(nlri.RF_IPv6_VPN)
|
||||
vpn_table = self._global_tables.get(RF_IPv6_VPN)
|
||||
# Lazy initialize the table.
|
||||
if not vpn_table:
|
||||
vpn_table = Vpnv6Table(self._core_service, self._signal_bus)
|
||||
self._global_tables[nlri.RF_IPv6_VPN] = vpn_table
|
||||
self._tables[(None, nlri.RF_IPv6_VPN)] = vpn_table
|
||||
self._global_tables[RF_IPv6_VPN] = vpn_table
|
||||
self._tables[(None, RF_IPv6_VPN)] = vpn_table
|
||||
|
||||
return vpn_table
|
||||
|
||||
@ -212,12 +225,12 @@ class TableCoreManager(object):
|
||||
|
||||
Creates the table if it does not exist.
|
||||
"""
|
||||
vpn_table = self._global_tables.get(nlri.RF_IPv4_VPN)
|
||||
vpn_table = self._global_tables.get(RF_IPv4_VPN)
|
||||
# Lazy initialize the table.
|
||||
if not vpn_table:
|
||||
vpn_table = Vpnv4Table(self._core_service, self._signal_bus)
|
||||
self._global_tables[nlri.RF_IPv4_VPN] = vpn_table
|
||||
self._tables[(None, nlri.RF_IPv4_VPN)] = vpn_table
|
||||
self._global_tables[RF_IPv4_VPN] = vpn_table
|
||||
self._tables[(None, RF_IPv4_VPN)] = vpn_table
|
||||
|
||||
return vpn_table
|
||||
|
||||
@ -226,12 +239,12 @@ class TableCoreManager(object):
|
||||
|
||||
Creates the table if it does not exist.
|
||||
"""
|
||||
rtc_table = self._global_tables.get(nlri.RF_RTC_UC)
|
||||
rtc_table = self._global_tables.get(RF_RTC_UC)
|
||||
# Lazy initialization of the table.
|
||||
if not rtc_table:
|
||||
rtc_table = RtcTable(self._core_service, self._signal_bus)
|
||||
self._global_tables[nlri.RF_RTC_UC] = rtc_table
|
||||
self._tables[(None, nlri.RF_RTC_UC)] = rtc_table
|
||||
self._global_tables[RF_RTC_UC] = rtc_table
|
||||
self._tables[(None, RF_RTC_UC)] = rtc_table
|
||||
return rtc_table
|
||||
|
||||
def get_next_vpnv4_label(self):
|
||||
@ -379,7 +392,7 @@ class TableCoreManager(object):
|
||||
for route_family in SUPPORTED_GLOBAL_RF:
|
||||
# TODO(PH): We currently do not install RT_NLRI paths based on
|
||||
# extended path attributes (RT)
|
||||
if route_family == nlri.RF_RTC_UC:
|
||||
if route_family == RF_RTC_UC:
|
||||
continue
|
||||
table = self.get_global_table_by_route_family(route_family)
|
||||
uninteresting_dest_count += \
|
||||
@ -407,9 +420,9 @@ class TableCoreManager(object):
|
||||
interested_tables = set()
|
||||
|
||||
# Get route family of VRF to when this VPN Path can be imported to
|
||||
route_family = nlri.RF_IPv4_UC
|
||||
if vpn_path.route_family != nlri.RF_IPv4_VPN:
|
||||
route_family = nlri.RF_IPv6_UC
|
||||
route_family = RF_IPv4_UC
|
||||
if vpn_path.route_family != RF_IPv4_VPN:
|
||||
route_family = RF_IPv6_UC
|
||||
for rt in path_rts:
|
||||
rt_rf_id = rt + ':' + str(route_family)
|
||||
vrf_rt_tables = self._tables_for_rt.get(rt_rf_id)
|
||||
@ -454,7 +467,8 @@ class TableCoreManager(object):
|
||||
'exist.' % route_dist)
|
||||
if not is_valid_ipv4_prefix(prefix) or not is_valid_ipv4(next_hop):
|
||||
raise BgpCoreError(desc='Invalid Ipv4 prefix or nexthop.')
|
||||
prefix = nlri.Ipv4(prefix)
|
||||
ip, masklen = prefix.split('/')
|
||||
prefix = IPAddrPrefix(int(masklen), ip)
|
||||
elif route_family == VRF_RF_IPV6:
|
||||
vrf_table = self._tables.get(table_id)
|
||||
if vrf_table is None:
|
||||
@ -462,24 +476,26 @@ class TableCoreManager(object):
|
||||
'exist.' % route_dist)
|
||||
if not is_valid_ipv6_prefix(prefix) or not is_valid_ipv6(next_hop):
|
||||
raise BgpCoreError(desc='Invalid Ipv6 prefix or nexthop.')
|
||||
prefix = nlri.Ipv6(prefix)
|
||||
ip6, masklen = prefix.split('/')
|
||||
prefix = IP6AddrPrefix(int(masklen), ip6)
|
||||
return vrf_table.insert_vrf_path(
|
||||
prefix, next_hop=next_hop,
|
||||
gen_lbl=True
|
||||
)
|
||||
|
||||
def add_to_ipv4_global_table(self, prefix):
|
||||
_nlri = nlri.Ipv4(prefix)
|
||||
ip, masklen = prefix.split('/')
|
||||
_nlri = IPAddrPrefix(int(masklen), ip)
|
||||
src_ver_num = 1
|
||||
peer = None
|
||||
# set mandatory path attributes
|
||||
nexthop = pathattr.NextHop("0.0.0.0")
|
||||
origin = pathattr.Origin('igp')
|
||||
aspath = pathattr.AsPath([[]])
|
||||
nexthop = BGPPathAttributeNextHop("0.0.0.0")
|
||||
origin = BGPPathAttributeOrigin(BGP_ATTR_ORIGIN_IGP)
|
||||
aspath = BGPPathAttributeAsPath([[]])
|
||||
|
||||
pathattrs = OrderedDict()
|
||||
pathattrs[origin.ATTR_NAME] = origin
|
||||
pathattrs[aspath.ATTR_NAME] = aspath
|
||||
pathattrs[BGP_ATTR_TYPE_ORIGIN] = origin
|
||||
pathattrs[BGP_ATTR_TYPE_AS_PATH] = aspath
|
||||
|
||||
new_path = Ipv4Path(peer, _nlri, src_ver_num,
|
||||
pattrs=pathattrs, nexthop=nexthop)
|
||||
@ -510,13 +526,15 @@ class TableCoreManager(object):
|
||||
if not vrf_table:
|
||||
raise BgpCoreError(desc='Vrf for route distinguisher %s does '
|
||||
'not exist.' % route_dist)
|
||||
prefix = nlri.Ipv4(prefix)
|
||||
ip, masklen = prefix.split('/')
|
||||
prefix = IPAddrPrefix(int(masklen), ip)
|
||||
else:
|
||||
vrf_table = self._tables.get(table_id)
|
||||
if not vrf_table:
|
||||
raise BgpCoreError(desc='Vrf for route distinguisher %s does '
|
||||
'not exist.' % route_dist)
|
||||
prefix = nlri.Ipv6(prefix)
|
||||
ip6, masklen = prefix.split('/')
|
||||
prefix = IP6AddrPrefix(int(masklen), ip)
|
||||
# We do not check if we have a path to given prefix, we issue
|
||||
# withdrawal. Hence multiple withdrawals have not side effect.
|
||||
return vrf_table.insert_vrf_path(prefix, is_withdraw=True)
|
||||
|
||||
@ -24,9 +24,9 @@ from abc import abstractmethod
|
||||
from copy import copy
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RtNlri
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import ExtCommunity
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RouteTargetMembershipNLRI
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_EXTENDED_COMMUNITIES
|
||||
|
||||
from ryu.services.protocols.bgp.base import OrderedDict
|
||||
from ryu.services.protocols.bgp.constants import VPN_TABLE
|
||||
@ -169,7 +169,7 @@ class Table(object):
|
||||
def _validate_nlri(self, nlri):
|
||||
"""Validated *nlri* is the type that this table stores/supports.
|
||||
"""
|
||||
if not nlri or not (nlri.route_family == self.route_family):
|
||||
if not nlri or not (nlri.ROUTE_FAMILY == self.route_family):
|
||||
raise ValueError('Invalid Vpnv4 prefix given.')
|
||||
|
||||
def _validate_path(self, path):
|
||||
@ -661,10 +661,10 @@ class Path(object):
|
||||
- `is_withdraw`: (bool) True if this represents a withdrawal.
|
||||
"""
|
||||
self.med_set_by_target_neighbor = med_set_by_target_neighbor
|
||||
if nlri.route_family != self.__class__.ROUTE_FAMILY:
|
||||
if nlri.ROUTE_FAMILY != self.__class__.ROUTE_FAMILY:
|
||||
raise ValueError('NLRI and Path route families do not'
|
||||
' match (%s, %s).' %
|
||||
(nlri.route_family, self.__class__.ROUTE_FAMILY))
|
||||
(nlri.ROUTE_FAMILY, self.__class__.ROUTE_FAMILY))
|
||||
|
||||
# Currently paths injected directly into VRF has only one source
|
||||
# src_peer can be None to denote NC else has to be instance of Peer.
|
||||
@ -760,7 +760,8 @@ class Path(object):
|
||||
return clone
|
||||
|
||||
def get_rts(self):
|
||||
extcomm_attr = self._path_attr_map.get(ExtCommunity.ATTR_NAME)
|
||||
extcomm_attr = self._path_attr_map.get(
|
||||
BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
|
||||
if extcomm_attr is None:
|
||||
rts = []
|
||||
else:
|
||||
@ -775,7 +776,7 @@ class Path(object):
|
||||
curr_rts = self.get_rts()
|
||||
# Add default RT to path RTs so that we match interest for peers who
|
||||
# advertised default RT
|
||||
curr_rts.append(RtNlri.DEFAULT_RT)
|
||||
curr_rts.append(RouteTargetMembershipNLRI.DEFAULT_RT)
|
||||
|
||||
return not interested_rts.isdisjoint(curr_rts)
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import Ipv4
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import IPAddrPrefix
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
|
||||
from ryu.services.protocols.bgp.info_base.base import Path
|
||||
from ryu.services.protocols.bgp.info_base.base import Table
|
||||
@ -63,7 +63,7 @@ class Ipv4Path(Path):
|
||||
"""Represents a way of reaching an VPNv4 destination."""
|
||||
ROUTE_FAMILY = RF_IPv4_UC
|
||||
VRF_PATH_CLASS = None # defined in init - anti cyclic import hack
|
||||
NLRI_CLASS = Ipv4
|
||||
NLRI_CLASS = IPAddrPrefix
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Ipv4Path, self).__init__(*args, **kwargs)
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_RTC_UC
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
|
||||
from ryu.services.protocols.bgp.info_base.base import Destination
|
||||
from ryu.services.protocols.bgp.info_base.base import NonVrfPathProcessingMixin
|
||||
|
||||
@ -19,8 +19,8 @@
|
||||
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import Ipv4
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import IPAddrPrefix
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
|
||||
from ryu.services.protocols.bgp.info_base.vpn import VpnDest
|
||||
from ryu.services.protocols.bgp.info_base.vpn import VpnPath
|
||||
@ -51,7 +51,7 @@ class Vpnv4Path(VpnPath):
|
||||
"""Represents a way of reaching an VPNv4 destination."""
|
||||
ROUTE_FAMILY = RF_IPv4_VPN
|
||||
VRF_PATH_CLASS = None # defined in init - anti cyclic import hack
|
||||
NLRI_CLASS = Ipv4
|
||||
NLRI_CLASS = IPAddrPrefix
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Vpnv4Path, self).__init__(*args, **kwargs)
|
||||
|
||||
@ -19,8 +19,8 @@
|
||||
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import Ipv6
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import IP6AddrPrefix
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
|
||||
from ryu.services.protocols.bgp.info_base.vpn import VpnDest
|
||||
from ryu.services.protocols.bgp.info_base.vpn import VpnPath
|
||||
@ -51,7 +51,7 @@ class Vpnv6Path(VpnPath):
|
||||
"""Represents a way of reaching an VPNv4 destination."""
|
||||
ROUTE_FAMILY = RF_IPv6_VPN
|
||||
VRF_PATH_CLASS = None # defined in init - anti cyclic import hack
|
||||
NLRI_CLASS = Ipv6
|
||||
NLRI_CLASS = IP6AddrPrefix
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Vpnv6Path, self).__init__(*args, **kwargs)
|
||||
|
||||
@ -20,6 +20,15 @@
|
||||
import abc
|
||||
import logging
|
||||
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_EXTENDED_COMMUNITIES
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MULTI_EXIT_DISC
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeOrigin
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeAsPath
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeExtendedCommunities
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeMultiExitDisc
|
||||
|
||||
from ryu.services.protocols.bgp.base import OrderedDict
|
||||
from ryu.services.protocols.bgp.constants import VPN_TABLE
|
||||
from ryu.services.protocols.bgp.constants import VRF_TABLE
|
||||
@ -30,7 +39,6 @@ from ryu.services.protocols.bgp.utils.stats import LOCAL_ROUTES
|
||||
from ryu.services.protocols.bgp.utils.stats import REMOTE_ROUTES
|
||||
from ryu.services.protocols.bgp.utils.stats import RESOURCE_ID
|
||||
from ryu.services.protocols.bgp.utils.stats import RESOURCE_NAME
|
||||
from ryu.services.protocols.bgp.protocols.bgp import pathattr
|
||||
|
||||
LOG = logging.getLogger('bgpspeaker.info_base.vrf')
|
||||
|
||||
@ -201,15 +209,15 @@ class VrfTable(Table):
|
||||
# in the path. Hence we do not add these attributes here.
|
||||
from ryu.services.protocols.bgp.core import EXPECTED_ORIGIN
|
||||
|
||||
pattrs[pathattr.Origin.ATTR_NAME] = \
|
||||
pathattr.Origin(EXPECTED_ORIGIN)
|
||||
pattrs[pathattr.AsPath.ATTR_NAME] = pathattr.AsPath([])
|
||||
pattrs[pathattr.ExtCommunity.ATTR_NAME] = pathattr.ExtCommunity(
|
||||
pattrs[BGP_ATTR_TYPE_ORIGIN] = BGPPathAttributeOrigin(
|
||||
EXPECTED_ORIGIN)
|
||||
pattrs[BGP_ATTR_TYPE_AS_PATH] = BGPPathAttributeAsPath([])
|
||||
pattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = \
|
||||
BGPPathAttributeExtendedCommunities(
|
||||
rt_list=vrf_conf.export_rts, soo_list=vrf_conf.soo_list)
|
||||
if vrf_conf.multi_exit_disc:
|
||||
pattrs[pathattr.Med.ATTR_NAME] = pathattr.Med(
|
||||
vrf_conf.multi_exit_disc
|
||||
)
|
||||
pattrs[BGP_ATTR_TYPE_MULTI_EXIT_DISC] = \
|
||||
BGPPathAttributeMultiExitDisc(vrf_conf.multi_exit_disc)
|
||||
|
||||
table_manager = self._core_service.table_manager
|
||||
if gen_lbl and next_hop:
|
||||
@ -526,5 +534,5 @@ class VrfRtImportMap(ImportMap):
|
||||
self._rt = rt
|
||||
|
||||
def match(self, vrf_path):
|
||||
extcomm = vrf_path.pathattr_map.get('extcommunity')
|
||||
extcomm = vrf_path.pathattr_map.get(BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
|
||||
return extcomm is not None and self._rt in extcomm.rt_list
|
||||
|
||||
@ -21,10 +21,10 @@
|
||||
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import Ipv4
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_VPN
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import Vpnv4
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import IPAddrPrefix
|
||||
from ryu.lib.packet.bgp import LabelledVPNIPAddrPrefix
|
||||
|
||||
from ryu.services.protocols.bgp.info_base.vpnv4 import Vpnv4Path
|
||||
from ryu.services.protocols.bgp.info_base.vrf import VrfDest
|
||||
@ -39,7 +39,7 @@ class Vrf4Path(VrfPath):
|
||||
"""Represents a way of reaching an IP destination with a VPN."""
|
||||
ROUTE_FAMILY = RF_IPv4_UC
|
||||
VPN_PATH_CLASS = Vpnv4Path
|
||||
VPN_NLRI_CLASS = Vpnv4
|
||||
VPN_NLRI_CLASS = LabelledVPNIPAddrPrefix
|
||||
|
||||
|
||||
class Vrf4Dest(VrfDest):
|
||||
@ -50,11 +50,11 @@ class Vrf4Table(VrfTable):
|
||||
"""Virtual Routing and Forwarding information base for IPv4."""
|
||||
ROUTE_FAMILY = RF_IPv4_UC
|
||||
VPN_ROUTE_FAMILY = RF_IPv4_VPN
|
||||
NLRI_CLASS = Ipv4
|
||||
NLRI_CLASS = IPAddrPrefix
|
||||
VRF_PATH_CLASS = Vrf4Path
|
||||
VRF_DEST_CLASS = Vrf4Dest
|
||||
|
||||
|
||||
class Vrf4NlriImportMap(VrfNlriImportMap):
|
||||
VRF_PATH_CLASS = Vrf4Path
|
||||
NLRI_CLASS = Ipv4
|
||||
NLRI_CLASS = IPAddrPrefix
|
||||
|
||||
@ -21,10 +21,10 @@
|
||||
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import Ipv6
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv6_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv6_VPN
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import Vpnv6
|
||||
from ryu.lib.packet.bgp import RF_IPv6_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import IP6AddrPrefix
|
||||
from ryu.lib.packet.bgp import LabelledVPNIP6AddrPrefix
|
||||
|
||||
from ryu.services.protocols.bgp.info_base.vpnv6 import Vpnv6Path
|
||||
from ryu.services.protocols.bgp.info_base.vrf import VrfDest
|
||||
@ -39,7 +39,7 @@ class Vrf6Path(VrfPath):
|
||||
"""Represents a way of reaching an IP destination with a VPN."""
|
||||
ROUTE_FAMILY = RF_IPv6_UC
|
||||
VPN_PATH_CLASS = Vpnv6Path
|
||||
VPN_NLRI_CLASS = Vpnv6
|
||||
VPN_NLRI_CLASS = LabelledVPNIP6AddrPrefix
|
||||
|
||||
|
||||
class Vrf6Dest(VrfDest):
|
||||
@ -51,11 +51,11 @@ class Vrf6Table(VrfTable):
|
||||
"""Virtual Routing and Forwarding information base for IPv6."""
|
||||
ROUTE_FAMILY = RF_IPv6_UC
|
||||
VPN_ROUTE_FAMILY = RF_IPv6_VPN
|
||||
NLRI_CLASS = Ipv6
|
||||
NLRI_CLASS = IP6AddrPrefix
|
||||
VRF_PATH_CLASS = Vrf6Path
|
||||
VRF_DEST_CLASS = Vrf6Dest
|
||||
|
||||
|
||||
class Vrf6NlriImportMap(VrfNlriImportMap):
|
||||
VRF_PATH_CLASS = Vrf6Path
|
||||
NLRI_CLASS = Ipv6
|
||||
NLRI_CLASS = IP6AddrPrefix
|
||||
|
||||
@ -8,10 +8,10 @@ from ryu.services.protocols.bgp.operator.command import STATUS_OK
|
||||
from ryu.services.protocols.bgp.operator.commands.responses import \
|
||||
WrongParamResp
|
||||
from ryu.services.protocols.bgp.operator.views.bgp import CoreServiceDetailView
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_VPN
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv6_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv6_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
|
||||
LOG = logging.getLogger('bgpspeaker.operator.commands.show.summary')
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp import nlri
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import AsPath
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import Med
|
||||
from ryu.lib.packet.bgp import RouteFamily
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv6_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
|
||||
from ryu.services.protocols.bgp.base import add_bgp_error_metadata
|
||||
from ryu.services.protocols.bgp.base import BGPSException
|
||||
from ryu.services.protocols.bgp.base import SUPPORTED_GLOBAL_RF
|
||||
@ -67,10 +71,11 @@ class InternalApi(object):
|
||||
|
||||
def get_single_rib_routes(self, addr_family):
|
||||
rfs = {
|
||||
'ipv4': nlri.get_rf(1, 1),
|
||||
'vpnv4': nlri.get_rf(1, 128),
|
||||
'vpnv6': nlri.get_rf(2, 128),
|
||||
'rtfilter': nlri.get_rf(1, 132)
|
||||
'ipv4': RF_IPv4_UC,
|
||||
'ipv6': RF_IPv6_UC,
|
||||
'vpnv4': RF_IPv4_VPN,
|
||||
'vpnv6': RF_IPv6_VPN,
|
||||
'rtfilter': RF_RTC_UC
|
||||
}
|
||||
if addr_family not in rfs:
|
||||
raise WrongParamError('Unknown or unsupported family')
|
||||
@ -89,13 +94,13 @@ class InternalApi(object):
|
||||
'prefix': dst.nlri.formatted_nlri_str}
|
||||
|
||||
def _path_to_dict(dst, path):
|
||||
aspath = path.get_pattr(AsPath.ATTR_NAME).path_seg_list
|
||||
aspath = path.get_pattr(BGP_ATTR_TYPE_AS_PATH).path_seg_list
|
||||
if aspath is None or len(aspath) == 0:
|
||||
aspath = ''
|
||||
|
||||
nexthop = path.nexthop
|
||||
# Get the MED path attribute
|
||||
med = path.get_pattr(Med.ATTR_NAME)
|
||||
med = path.get_pattr(BGP_ATTR_TYPE_MULTI_EXIT_DISC)
|
||||
med = med.value if med else ''
|
||||
# Get best path reason
|
||||
bpr = dst.best_path_reason if path == dst.best_path else ''
|
||||
@ -134,7 +139,7 @@ class InternalApi(object):
|
||||
if afi is None and safi is None:
|
||||
route_families.extend(SUPPORTED_GLOBAL_RF)
|
||||
else:
|
||||
route_family = nlri.get_rf(afi, safi)
|
||||
route_family = RouteFamily(afi, safi)
|
||||
if (route_family not in SUPPORTED_GLOBAL_RF):
|
||||
raise WrongParamError('Not supported address-family'
|
||||
' %s, %s' % (afi, safi))
|
||||
|
||||
@ -5,8 +5,11 @@ from ryu.services.protocols.bgp.operator.views.base import \
|
||||
from ryu.services.protocols.bgp.operator.views.base import OperatorDetailView
|
||||
from ryu.services.protocols.bgp.operator.views import fields
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp import pathattr
|
||||
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MULTI_EXIT_DISC
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_LOCAL_PREF
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_EXTENDED_COMMUNITIES
|
||||
|
||||
class CoreServiceDetailView(OperatorDetailView):
|
||||
rf_state = fields.RelatedViewField(
|
||||
@ -144,18 +147,19 @@ class PathDetailView(OperatorDetailView):
|
||||
ret = super(PathDetailView, self).encode()
|
||||
ret['nlri'] = self.rel('nlri').encode()
|
||||
ret['route_family'] = self.rel('route_family').encode()
|
||||
as_path = self.get_field('pathattr_map').get(pathattr.AsPath.ATTR_NAME)
|
||||
origin = self.get_field('pathattr_map').get(pathattr.Origin.ATTR_NAME)
|
||||
metric = self.get_field('pathattr_map').get(pathattr.Med.ATTR_NAME)
|
||||
as_path = self.get_field('pathattr_map').get(BGP_ATTR_TYPE_AS_PATH)
|
||||
origin = self.get_field('pathattr_map').get(BGP_ATTR_TYPE_ORIGIN)
|
||||
metric = self.get_field('pathattr_map').get(
|
||||
BGP_ATTR_TYPE_MULTI_EXIT_DISC)
|
||||
local_pref = self.get_field('pathattr_map').get(
|
||||
pathattr.LocalPref.ATTR_NAME
|
||||
BGP_ATTR_TYPE_LOCAL_PREF
|
||||
)
|
||||
|
||||
ret['as_path'] = as_path.value if as_path else None
|
||||
ret['origin'] = origin.value if origin else None
|
||||
ret['metric'] = metric.value if metric else None
|
||||
ret['local_pref'] = local_pref.value if local_pref else None
|
||||
ext = ret['pathattr_map'].get(pathattr.ExtCommunity.ATTR_NAME)
|
||||
ext = ret['pathattr_map'].get(BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
|
||||
del ret['pathattr_map']
|
||||
if ext:
|
||||
ret['rt_list'] = ext.rt_list
|
||||
@ -215,11 +219,13 @@ class VpnNlriDetailView(IpNlriDetailView):
|
||||
|
||||
class NlriDetailView(OperatorDetailView):
|
||||
def __new__(cls, obj, filter_func=None):
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import Vpnv4, Vpnv6
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import Ipv4, Ipv6
|
||||
if isinstance(obj, (Vpnv4, Vpnv6)):
|
||||
from ryu.lib.packet.bgp import LabelledVPNIPAddrPrefix
|
||||
from ryu.lib.packet.bgp import LabelledVPNIP6AddrPrefix
|
||||
from ryu.lib.packet.bgp import IPAddrPrefix, IP6AddrPrefix
|
||||
if isinstance(obj, (LabelledVPNIPAddrPrefix,
|
||||
LabelledVPNIP6AddrPrefix)):
|
||||
return VpnNlriDetailView(obj)
|
||||
elif isinstance(obj, (Ipv4, Ipv6)):
|
||||
elif isinstance(obj, (IPAddrPrefix, IP6AddrPrefix)):
|
||||
return IpNlriDetailView(obj)
|
||||
else:
|
||||
return OperatorDetailView(obj, filter_func)
|
||||
|
||||
@ -36,11 +36,39 @@ from ryu.services.protocols.bgp.speaker import BgpProtocol
|
||||
from ryu.services.protocols.bgp.utils import bgp as bgp_utils
|
||||
from ryu.services.protocols.bgp.utils.evtlet import EventletIOFactory
|
||||
from ryu.services.protocols.bgp.utils import stats
|
||||
from ryu.services.protocols.bgp.protocols.bgp import exceptions
|
||||
from ryu.services.protocols.bgp.protocols.bgp import messages
|
||||
from ryu.services.protocols.bgp.protocols.bgp import nlri
|
||||
from ryu.services.protocols.bgp.protocols.bgp import pathattr
|
||||
|
||||
from ryu.lib.packet import bgp
|
||||
|
||||
from ryu.lib.packet.bgp import RouteFamily
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv6_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
|
||||
from ryu.lib.packet.bgp import BGPOpen
|
||||
from ryu.lib.packet.bgp import BGPUpdate
|
||||
from ryu.lib.packet.bgp import BGPRouteRefresh
|
||||
|
||||
from ryu.lib.packet.bgp import BGP_MSG_UPDATE
|
||||
from ryu.lib.packet.bgp import BGP_MSG_KEEPALIVE
|
||||
from ryu.lib.packet.bgp import BGP_MSG_ROUTE_REFRESH
|
||||
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeNextHop
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeAsPath
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeLocalPref
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeExtendedCommunities
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeMpReachNLRI
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeMpUnreachNLRI
|
||||
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_NEXT_HOP
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MP_REACH_NLRI
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MP_UNREACH_NLRI
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MULTI_EXIT_DISC
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_COMMUNITIES
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_EXTENDED_COMMUNITIES
|
||||
|
||||
LOG = logging.getLogger('bgpspeaker.peer')
|
||||
|
||||
@ -110,7 +138,7 @@ class PeerState(object):
|
||||
}
|
||||
self._signal_bus = signal_bus
|
||||
|
||||
#TODO(JK): refactor other counters to use signals also
|
||||
# TODO(JK): refactor other counters to use signals also
|
||||
self._signal_bus.register_listener(
|
||||
('error', 'bgp', self.peer),
|
||||
self._remember_last_bgp_error
|
||||
@ -264,12 +292,12 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# State per route family, {RouteFamily: PeerRf,}.
|
||||
self.rf_state = {}
|
||||
# Get vpnv4 route family settings.
|
||||
prf = PeerRf(self, nlri.RF_IPv4_VPN,
|
||||
prf = PeerRf(self, RF_IPv4_VPN,
|
||||
enabled=self._neigh_conf.cap_mbgp_vpnv4)
|
||||
self.rf_state[nlri.RF_IPv4_VPN] = prf
|
||||
self.rf_state[RF_IPv4_VPN] = prf
|
||||
# Get vpnv6 route family settings.
|
||||
prf = PeerRf(self, nlri.RF_IPv6_VPN, self._neigh_conf.cap_mbgp_vpnv6)
|
||||
self.rf_state[nlri.RF_IPv6_VPN] = prf
|
||||
prf = PeerRf(self, RF_IPv6_VPN, self._neigh_conf.cap_mbgp_vpnv6)
|
||||
self.rf_state[RF_IPv6_VPN] = prf
|
||||
|
||||
# Bound protocol instance
|
||||
self._protocol = None
|
||||
@ -378,8 +406,8 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# when we stop the protocol, hence we call connection_lost
|
||||
# here as we triggered socket to close.
|
||||
self._protocol.send_notification(
|
||||
exceptions.AdminShutdown.CODE,
|
||||
exceptions.AdminShutdown.SUB_CODE
|
||||
BGP_ERROR_CEASE,
|
||||
BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN
|
||||
)
|
||||
self._protocol.stop()
|
||||
# If this peer is not enabled any-more we stop trying to make any
|
||||
@ -415,7 +443,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
|
||||
Update appropriate counters and set appropriate timers.
|
||||
"""
|
||||
assert rr_msg.TYPE_CODE == messages.RouteRefresh.TYPE_CODE
|
||||
assert rr_msg.TYPE_CODE == BGP_MSG_ROUTE_REFRESH
|
||||
self._protocol.send(rr_msg)
|
||||
LOG.debug('RouteRefresh %s>> %s' %
|
||||
(self._neigh_conf.ip_address, rr_msg))
|
||||
@ -471,18 +499,18 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# Check currently supported out-going msgs.
|
||||
assert isinstance(
|
||||
outgoing_msg,
|
||||
(messages.RouteRefresh, messages.Update, OutgoingRoute)
|
||||
(BGPRouteRefresh, BGPUpdate, OutgoingRoute)
|
||||
), ('Peer cannot process object: %s in its outgoing queue'
|
||||
% outgoing_msg)
|
||||
|
||||
# Send msg. to peer.
|
||||
if isinstance(outgoing_msg, messages.RouteRefresh):
|
||||
if isinstance(outgoing_msg, BGPRouteRefresh):
|
||||
self._send_outgoing_route_refresh_msg(outgoing_msg)
|
||||
elif isinstance(outgoing_msg, OutgoingRoute):
|
||||
self._send_outgoing_route(outgoing_msg)
|
||||
|
||||
# EOR are enqueued as plain Update messages.
|
||||
elif isinstance(outgoing_msg, messages.Update):
|
||||
elif isinstance(outgoing_msg, BGPUpdate):
|
||||
self._protocol.send(outgoing_msg)
|
||||
LOG.debug('Update %s>> %s' % (self._neigh_conf.ip_address,
|
||||
outgoing_msg))
|
||||
@ -523,17 +551,17 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# We ignore request for route_family not valid
|
||||
# for current session.
|
||||
self._protocol.is_mbgp_cap_valid(route_family))):
|
||||
rr_req = messages.RouteRefresh(route_family)
|
||||
rr_req = BGPRouteRefresh(route_family.afi, route_family.safi)
|
||||
self.enque_outgoing_msg(rr_req)
|
||||
LOG.debug('Enqueued Route Refresh message to '
|
||||
'peer %s for rf: %s' % (self, route_family))
|
||||
|
||||
def enque_end_of_rib(self, route_family):
|
||||
pattr_map = {}
|
||||
# MP_UNREACH_NLRI Attribute.
|
||||
mpunreach_attr = pathattr.MpUnreachNlri(route_family, [])
|
||||
pattr_map[pathattr.MpUnreachNlri.ATTR_NAME] = mpunreach_attr
|
||||
update = messages.Update(pathattr_map=pattr_map)
|
||||
mpunreach_attr = BGPPathAttributeMpUnreachNLRI(route_family.afi,
|
||||
route_family.safi,
|
||||
[])
|
||||
update = BGPUpdate(path_attributes=[mpunreach_attr])
|
||||
self.enque_outgoing_msg(update)
|
||||
|
||||
def _session_next_hop(self, route_family):
|
||||
@ -546,9 +574,13 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
"""
|
||||
# By default we use BGPS's interface IP with this peer as next_hop.
|
||||
next_hop = self._neigh_conf.host_bind_ip
|
||||
if route_family == nlri.RF_IPv6_VPN:
|
||||
if route_family == RF_IPv6_VPN:
|
||||
# Next hop ipv4_mapped ipv6
|
||||
next_hop = nlri.ipv4_mapped_ipv6(next_hop)
|
||||
def _ipv4_mapped_ipv6(ipv4):
|
||||
from netaddr import IPAddress
|
||||
return str(IPAddress(ipv4).ipv6())
|
||||
|
||||
next_hop = _ipv4_mapped_ipv6(next_hop)
|
||||
|
||||
return next_hop
|
||||
|
||||
@ -556,8 +588,7 @@ 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:
|
||||
if self._neigh_conf.cap_mbgp_ipv4:
|
||||
update = self._construct_bgp4_update(outgoing_route)
|
||||
else:
|
||||
update = self._construct_mpbgp_update(outgoing_route)
|
||||
@ -569,10 +600,10 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
path = outgoing_route.path
|
||||
# Get copy of path's path attributes.
|
||||
pathattr_map = path.pathattr_map
|
||||
new_pathattr_map = OrderedDict()
|
||||
new_pathattr = []
|
||||
|
||||
if path.is_withdraw:
|
||||
update = messages.Update(withdraw_list=path.nlri)
|
||||
update = BGPUpdate(withdrawn_routes=[path.nlri])
|
||||
return update
|
||||
else:
|
||||
# Supported and un-supported/unknown attributes.
|
||||
@ -595,19 +626,19 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# 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)
|
||||
nexthop_attr = BGPPathAttributeNextHop(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)
|
||||
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(pathattr.AsPath.ATTR_NAME)
|
||||
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
|
||||
@ -616,7 +647,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# 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)
|
||||
aspath_attr = BGPPathAttributeAsPath(path_seg_list)
|
||||
else:
|
||||
# When a given BGP speaker advertises the route to an external
|
||||
# peer, the advertising speaker updates the AS_PATH attribute
|
||||
@ -644,15 +675,16 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
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)
|
||||
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(pathattr.Med.ATTR_NAME)
|
||||
multi_exit_disc = pathattr_map.get(
|
||||
BGP_ATTR_TYPE_MULTI_EXIT_DISC)
|
||||
if not multi_exit_disc and self._neigh_conf.multi_exit_disc:
|
||||
multi_exit_disc = pathattr.Med(
|
||||
multi_exit_disc = BGPPathAttributeMultiExitDisc(
|
||||
self._neigh_conf.multi_exit_disc
|
||||
)
|
||||
|
||||
@ -660,15 +692,15 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
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)
|
||||
localpref_attr = BGPPathAttributeLocalPref(100)
|
||||
|
||||
# COMMUNITY Attribute.
|
||||
community_attr = pathattr_map.get(pathattr.Community.ATTR_NAME)
|
||||
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(
|
||||
pathattr.ExtCommunity.ATTR_NAME
|
||||
BGP_ATTR_TYPE_EXTENDED_COMMUNITIES
|
||||
)
|
||||
if path_extcomm_attr:
|
||||
# SOO list can be configured per VRF and/or per Neighbor.
|
||||
@ -676,7 +708,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
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(
|
||||
extcomm_attr = BGPPathAttributeExtendedCommunities(
|
||||
path_extcomm_attr.rt_list,
|
||||
soo_list
|
||||
)
|
||||
@ -688,22 +720,22 @@ 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_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
|
||||
new_pathattr.append(nexthop_attr)
|
||||
new_pathattr.append(origin_attr)
|
||||
new_pathattr.append(aspath_attr)
|
||||
if multi_exit_disc:
|
||||
new_pathattr_map[pathattr.Med.ATTR_NAME] = multi_exit_disc
|
||||
new_pathattr.append(multi_exit_disc)
|
||||
if localpref_attr:
|
||||
new_pathattr_map[pathattr.LocalPref.ATTR_NAME] = localpref_attr
|
||||
new_pathattr.append(localpref_attr)
|
||||
if community_attr:
|
||||
new_pathattr_map[pathattr.Community.ATTR_NAME] = community_attr
|
||||
new_pathattr.append(community_attr)
|
||||
if extcomm_attr:
|
||||
new_pathattr_map[pathattr.ExtCommunity.ATTR_NAME] =\
|
||||
extcomm_attr
|
||||
new_pathattr.append(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)
|
||||
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):
|
||||
@ -715,16 +747,16 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
path = outgoing_route.path
|
||||
# Get copy of path's path attributes.
|
||||
pathattr_map = path.pathattr_map
|
||||
new_pathattr_map = OrderedDict()
|
||||
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 = pathattr.MpUnreachNlri(
|
||||
path.route_family, [path.nlri]
|
||||
mpunreach_attr = BGPPathAttributeMpUnreachNLRI(
|
||||
path.route_family.afi, path.route_family.safi, [path.nlri]
|
||||
)
|
||||
new_pathattr_map[pathattr.MpUnreachNlri.ATTR_NAME] = mpunreach_attr
|
||||
new_pathattr.append(mpunreach_attr)
|
||||
else:
|
||||
# Supported and un-supported/unknown attributes.
|
||||
origin_attr = None
|
||||
@ -746,20 +778,23 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# to RFC 4271 we should not modify next_hop.
|
||||
next_hop = path.nexthop
|
||||
# We construct mpreach-nlri attribute.
|
||||
mpnlri_attr = pathattr.MpReachNlri(
|
||||
path.route_family, next_hop, [path.nlri]
|
||||
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(pathattr.Origin.ATTR_NAME)
|
||||
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(pathattr.AsPath.ATTR_NAME)
|
||||
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
|
||||
@ -768,7 +803,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# 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)
|
||||
aspath_attr = BGPPathAttributeAsPath(path_seg_list)
|
||||
else:
|
||||
# When a given BGP speaker advertises the route to an external
|
||||
# peer, the advertising speaker updates the AS_PATH attribute
|
||||
@ -796,13 +831,14 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
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)
|
||||
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(pathattr.Med.ATTR_NAME)
|
||||
multi_exit_disc = pathattr_map.get(
|
||||
BGP_ATTR_TYPE_MULTI_EXIT_DISC)
|
||||
|
||||
# LOCAL_PREF Attribute.
|
||||
if not self.is_ebgp_peer():
|
||||
@ -811,12 +847,12 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
localpref_attr = pathattr.LocalPref(100)
|
||||
|
||||
# COMMUNITY Attribute.
|
||||
community_attr = pathattr_map.get(pathattr.Community.ATTR_NAME)
|
||||
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(
|
||||
pathattr.ExtCommunity.ATTR_NAME
|
||||
BGP_ATTR_TYPE_EXTENDED_COMMUNITIES
|
||||
)
|
||||
if path_extcomm_attr:
|
||||
# SOO list can be configured per VRF and/or per Neighbor.
|
||||
@ -824,9 +860,8 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
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
|
||||
extcomm_attr = BGPPathAttributeExtendedCommunities(
|
||||
path_extcomm_attr.rt_list+soo_list
|
||||
)
|
||||
|
||||
# UNKOWN Attributes.
|
||||
@ -836,22 +871,21 @@ 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_map[pathattr.MpReachNlri.ATTR_NAME] = mpnlri_attr
|
||||
new_pathattr_map[pathattr.Origin.ATTR_NAME] = origin_attr
|
||||
new_pathattr_map[pathattr.AsPath.ATTR_NAME] = aspath_attr
|
||||
new_pathattr.append(mpnlri_attr)
|
||||
new_pathattr.append(origin_attr)
|
||||
new_pathattr.append(aspath_attr)
|
||||
if multi_exit_disc:
|
||||
new_pathattr_map[pathattr.Med.ATTR_NAME] = multi_exit_disc
|
||||
new_pathattr.append(multi_exit_disc)
|
||||
if localpref_attr:
|
||||
new_pathattr_map[pathattr.LocalPref.ATTR_NAME] = localpref_attr
|
||||
new_pathattr.append(localpref_attr)
|
||||
if community_attr:
|
||||
new_pathattr_map[pathattr.Community.ATTR_NAME] = community_attr
|
||||
new_pathattr.append(community_attr)
|
||||
if extcomm_attr:
|
||||
new_pathattr_map[pathattr.ExtCommunity.ATTR_NAME] =\
|
||||
extcomm_attr
|
||||
new_pathattr.append(extcomm_attr)
|
||||
if unkown_opttrans_attrs:
|
||||
new_pathattr_map.update(unkown_opttrans_attrs)
|
||||
new_pathattr.extend(unkown_opttrans_attrs.values())
|
||||
|
||||
update = messages.Update(pathattr_map=new_pathattr_map)
|
||||
update = BGPUpdate(path_attributes=new_pathattr)
|
||||
return update
|
||||
|
||||
def _connect_loop(self, client_factory):
|
||||
@ -923,8 +957,8 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
LOG.debug('Processing of outgoing msg. started for %s.' % self)
|
||||
|
||||
def _send_collision_err_and_stop(self, protocol):
|
||||
code = exceptions.CollisionResolution.CODE
|
||||
subcode = exceptions.CollisionResolution.SUB_CODE
|
||||
code = BGP_ERROR_CEASE
|
||||
subcode = BGP_ERROR_SUB_CONNECTION_COLLISION_RESOLUTION
|
||||
self._signal_bus.bgp_error(self, code, subcode, None)
|
||||
protocol.send_notification(code, subcode)
|
||||
protocol.stop()
|
||||
@ -1011,12 +1045,22 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
asnum = self._common_conf.local_as
|
||||
bgpid = self._common_conf.router_id
|
||||
holdtime = self._neigh_conf.hold_time
|
||||
open_msg = messages.Open(
|
||||
const.BGP_VERSION_NUM,
|
||||
asnum,
|
||||
holdtime,
|
||||
bgpid,
|
||||
self._neigh_conf.get_configured_capabilites()
|
||||
|
||||
def flatten(L):
|
||||
if isinstance(L, list):
|
||||
for i in xrange(len(L)):
|
||||
for e in flatten(L[i]):
|
||||
yield e
|
||||
else:
|
||||
yield L
|
||||
opts = list(flatten(
|
||||
self._neigh_conf.get_configured_capabilites().values()))
|
||||
open_msg = BGPOpen(
|
||||
my_as=asnum,
|
||||
bgp_identifier=bgpid,
|
||||
version=const.BGP_VERSION_NUM,
|
||||
hold_time=holdtime,
|
||||
opt_param=opts
|
||||
)
|
||||
return open_msg
|
||||
|
||||
@ -1028,35 +1072,35 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
library.
|
||||
"""
|
||||
# TODO(PH): finish providing implementation, currently low priority
|
||||
assert update_msg.TYPE_CODE == messages.Update.TYPE_CODE
|
||||
assert update_msg.type == BGP_MSG_UPDATE
|
||||
# An UPDATE message may be received only in the Established state.
|
||||
# Receiving an UPDATE message in any other state is an error.
|
||||
if self.state.bgp_state != const.BGP_FSM_ESTABLISHED:
|
||||
LOG.error('Received UPDATE message when not in ESTABLISHED'
|
||||
' state.')
|
||||
raise exceptions.FiniteStateMachineError()
|
||||
raise bgp.FiniteStateMachineError()
|
||||
|
||||
mp_reach_attr = update_msg.get_path_attr(
|
||||
pathattr.MpReachNlri.ATTR_NAME
|
||||
BGP_ATTR_TYPE_MP_REACH_NLRI
|
||||
)
|
||||
mp_unreach_attr = update_msg.get_path_attr(
|
||||
pathattr.MpUnreachNlri.ATTR_NAME
|
||||
BGP_ATTR_TYPE_MP_UNREACH_NLRI
|
||||
)
|
||||
|
||||
# non-MPBGP Update msg.
|
||||
if not (mp_reach_attr or mp_unreach_attr):
|
||||
LOG.info('Received UPDATE msg. with no MpReachNlri or '
|
||||
'MpUnReachNlri attribute.')
|
||||
if not self.is_mpbgp_cap_valid(nlri.RF_IPv4_UC):
|
||||
if not self.is_mpbgp_cap_valid(RF_IPv4_UC):
|
||||
LOG.error('Got UPDATE message with un-available'
|
||||
' afi/safi %s' % nlri.RF_IPv4_UC)
|
||||
nlri_list = update_msg.nlri_list
|
||||
' afi/safi %s' % RF_IPv4_UC)
|
||||
nlri_list = update_msg.nlri
|
||||
if len(nlri_list) > 0:
|
||||
# Check for missing well-known mandatory attributes.
|
||||
aspath = update_msg.get_path_attr(pathattr.AsPath.ATTR_NAME)
|
||||
aspath = update_msg.get_path_attr(BGP_ATTR_TYPE_AS_PATH)
|
||||
if not aspath:
|
||||
raise exceptions.MissingWellKnown(
|
||||
pathattr.AsPath.TYPE_CODE)
|
||||
raise bgp.MissingWellKnown(
|
||||
BGP_ATTR_TYPE_AS_PATH)
|
||||
|
||||
# We do not have a setting to enable/disable first-as check.
|
||||
# We by default do first-as check below.
|
||||
@ -1064,17 +1108,15 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
not aspath.has_matching_leftmost(self.remote_as)):
|
||||
LOG.error('First AS check fails. Raise appropriate'
|
||||
' exception.')
|
||||
raise exceptions.MalformedAsPath()
|
||||
raise bgp.MalformedAsPath()
|
||||
|
||||
origin = update_msg.get_path_attr(pathattr.Origin.ATTR_NAME)
|
||||
origin = update_msg.get_path_attr(BGP_ATTR_TYPE_ORIGIN)
|
||||
if not origin:
|
||||
raise exceptions.MissingWellKnown(
|
||||
pathattr.Origin.TYPE_CODE)
|
||||
raise bgp.MissingWellKnown(BGP_ATTR_TYPE_ORIGIN)
|
||||
|
||||
nexthop = update_msg.get_path_attr(pathattr.NextHop.ATTR_NAME)
|
||||
nexthop = update_msg.get_path_attr(BGP_ATTR_TYPE_NEXT_HOP)
|
||||
if not nexthop:
|
||||
raise exceptions.MissingWellKnown(
|
||||
pathattr.NextHop.TYPE_CODE)
|
||||
raise bgp.MissingWellKnown(BGP_ATTR_TYPE_NEXT_HOP)
|
||||
|
||||
return True
|
||||
|
||||
@ -1084,7 +1126,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
LOG.error('Got UPDATE message with un-available afi/safi for'
|
||||
' MP_UNREACH path attribute (non-negotiated'
|
||||
' afi/safi) %s' % mp_unreach_attr.route_family)
|
||||
# raise exceptions.OptAttrError()
|
||||
# raise bgp.OptAttrError()
|
||||
|
||||
if mp_reach_attr:
|
||||
# Check if received MP_REACH path attribute is of available
|
||||
@ -1093,23 +1135,23 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
LOG.error('Got UPDATE message with un-available afi/safi for'
|
||||
' MP_UNREACH path attribute (non-negotiated'
|
||||
' afi/safi) %s' % mp_reach_attr.route_family)
|
||||
# raise exceptions.OptAttrError()
|
||||
# raise bgp.OptAttrError()
|
||||
|
||||
# Check for missing well-known mandatory attributes.
|
||||
aspath = update_msg.get_path_attr(pathattr.AsPath.ATTR_NAME)
|
||||
aspath = update_msg.get_path_attr(BGP_ATTR_TYPE_AS_PATH)
|
||||
if not aspath:
|
||||
raise exceptions.MissingWellKnown(pathattr.AsPath.TYPE_CODE)
|
||||
raise bgp.MissingWellKnown(BGP_ATTR_TYPE_AS_PATH)
|
||||
|
||||
# We do not have a setting to enable/disable first-as check.
|
||||
# We by default do first-as check below.
|
||||
if (self.is_ebgp_peer() and
|
||||
not aspath.has_matching_leftmost(self.remote_as)):
|
||||
LOG.error('First AS check fails. Raise appropriate exception.')
|
||||
raise exceptions.MalformedAsPath()
|
||||
raise bgp.MalformedAsPath()
|
||||
|
||||
origin = update_msg.get_path_attr(pathattr.Origin.ATTR_NAME)
|
||||
origin = update_msg.get_path_attr(BGP_ATTR_TYPE_ORIGIN)
|
||||
if not origin:
|
||||
raise exceptions.MissingWellKnown(pathattr.Origin.TYPE_CODE)
|
||||
raise bgp.MissingWellKnown(BGP_ATTR_TYPE_ORIGIN)
|
||||
|
||||
# Validate Next hop.
|
||||
# TODO(PH): Currently ignore other cases.
|
||||
@ -1142,15 +1184,13 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
return
|
||||
|
||||
# Increment count of update received.
|
||||
mp_reach_attr = update_msg.get_path_attr(
|
||||
pathattr.MpReachNlri.ATTR_NAME
|
||||
)
|
||||
mp_reach_attr = update_msg.get_path_attr(BGP_ATTR_TYPE_MP_REACH_NLRI)
|
||||
mp_unreach_attr = update_msg.get_path_attr(
|
||||
pathattr.MpUnreachNlri.ATTR_NAME
|
||||
BGP_ATTR_TYPE_MP_UNREACH_NLRI
|
||||
)
|
||||
|
||||
nlri_list = update_msg.nlri_list
|
||||
withdraw_list = update_msg.withdraw_list
|
||||
nlri_list = update_msg.nlri
|
||||
withdraw_list = update_msg.withdrawn_routes
|
||||
|
||||
if mp_reach_attr:
|
||||
# Extract advertised paths from given message.
|
||||
@ -1181,7 +1221,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
"""
|
||||
umsg_pattrs = update_msg.pathattr_map
|
||||
|
||||
msg_rf = nlri.RF_IPv4_UC
|
||||
msg_rf = RF_IPv4_UC
|
||||
# Check if this route family is among supported route families.
|
||||
if msg_rf not in SUPPORTED_GLOBAL_RF:
|
||||
LOG.info(('Received route for route family %s which is'
|
||||
@ -1189,16 +1229,16 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
(msg_rf, update_msg))
|
||||
return
|
||||
|
||||
aspath = umsg_pattrs.get(pathattr.AsPath.ATTR_NAME)
|
||||
aspath = umsg_pattrs.get(BGP_ATTR_TYPE_AS_PATH)
|
||||
# Check if AS_PATH has loops.
|
||||
if aspath.has_local_as(self._common_conf.local_as):
|
||||
LOG.error('Update message AS_PATH has loops. Ignoring this'
|
||||
' UPDATE. %s' % update_msg)
|
||||
return
|
||||
|
||||
next_hop = update_msg.get_path_attr(pathattr.NextHop.ATTR_NAME)
|
||||
next_hop = update_msg.get_path_attr(BGP_ATTR_TYPE_NEXT_HOP)
|
||||
# Nothing to do if we do not have any new NLRIs in this message.
|
||||
msg_nlri_list = update_msg.nlri_list
|
||||
msg_nlri_list = update_msg.nlri
|
||||
if not msg_nlri_list:
|
||||
LOG.debug('Update message did not have any new MP_REACH_NLRIs.')
|
||||
return
|
||||
@ -1240,7 +1280,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
Extracted withdraws are added to appropriate *Destination* for further
|
||||
processing.
|
||||
"""
|
||||
msg_rf = nlri.RF_IPv4_UC
|
||||
msg_rf = RF_IPv4_UC
|
||||
# Check if this route family is among supported route families.
|
||||
if msg_rf not in SUPPORTED_GLOBAL_RF:
|
||||
LOG.info(
|
||||
@ -1280,7 +1320,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
processing.
|
||||
"""
|
||||
umsg_pattrs = update_msg.pathattr_map
|
||||
mpreach_nlri_attr = umsg_pattrs.pop(pathattr.MpReachNlri.ATTR_NAME)
|
||||
mpreach_nlri_attr = umsg_pattrs.pop(BGP_ATTR_TYPE_MP_REACH_NLRI)
|
||||
assert mpreach_nlri_attr
|
||||
|
||||
msg_rf = mpreach_nlri_attr.route_family
|
||||
@ -1291,17 +1331,17 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
(msg_rf, update_msg))
|
||||
return
|
||||
|
||||
aspath = umsg_pattrs.get(pathattr.AsPath.ATTR_NAME)
|
||||
aspath = umsg_pattrs.get(BGP_ATTR_TYPE_AS_PATH)
|
||||
# Check if AS_PATH has loops.
|
||||
if aspath.has_local_as(self._common_conf.local_as):
|
||||
LOG.error('Update message AS_PATH has loops. Ignoring this'
|
||||
' UPDATE. %s' % update_msg)
|
||||
return
|
||||
|
||||
if msg_rf in (nlri.RF_IPv4_VPN, nlri.RF_IPv6_UC):
|
||||
if msg_rf in (RF_IPv4_VPN, RF_IPv6_UC):
|
||||
# Check if we have Extended Communities Attribute.
|
||||
# TODO(PH): Check if RT_NLRI afi/safi will ever have this attribute
|
||||
ext_comm_attr = umsg_pattrs.get(pathattr.ExtCommunity.ATTR_NAME)
|
||||
ext_comm_attr = umsg_pattrs.get(BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
|
||||
# Check if we have at-least one RT is of interest to us.
|
||||
if not ext_comm_attr:
|
||||
LOG.info('Missing Extended Communities Attribute. '
|
||||
@ -1328,7 +1368,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
|
||||
next_hop = mpreach_nlri_attr.next_hop
|
||||
# Nothing to do if we do not have any new NLRIs in this message.
|
||||
msg_nlri_list = mpreach_nlri_attr.nlri_list
|
||||
msg_nlri_list = mpreach_nlri_attr.nlri
|
||||
if not msg_nlri_list:
|
||||
LOG.debug('Update message did not have any new MP_REACH_NLRIs.')
|
||||
return
|
||||
@ -1342,7 +1382,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
nexthop=next_hop
|
||||
)
|
||||
LOG.debug('Extracted paths from Update msg.: %s' % new_path)
|
||||
if msg_rf == nlri.RF_RTC_UC \
|
||||
if msg_rf == RF_RTC_UC \
|
||||
and self._init_rtc_nlri_path is not None:
|
||||
self._init_rtc_nlri_path.append(new_path)
|
||||
else:
|
||||
@ -1408,7 +1448,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# assert (route_family in SUPPORTED_GLOBAL_RF)
|
||||
# assert self.is_mbgp_cap_valid(route_family)
|
||||
|
||||
if route_family == nlri.RF_RTC_UC:
|
||||
if route_family == RF_RTC_UC:
|
||||
self._unschedule_sending_init_updates()
|
||||
|
||||
# Learn all rt_nlri at the same time As RT are learned and RT
|
||||
@ -1434,19 +1474,19 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
KEEPALIVE, UPDATE and ROUTE_REFRESH messages. UPDATE and ROUTE_REFRESH
|
||||
messages are handled only after session is established.
|
||||
"""
|
||||
if msg.MSG_NAME == messages.Keepalive.MSG_NAME:
|
||||
if msg.type == BGP_MSG_KEEPALIVE:
|
||||
# If we receive a Keep Alive message in open_confirm state, we
|
||||
# transition to established state.
|
||||
if self.state.bgp_state == const.BGP_FSM_OPEN_CONFIRM:
|
||||
self.state.bgp_state = const.BGP_FSM_ESTABLISHED
|
||||
self._enqueue_init_updates()
|
||||
|
||||
elif msg.MSG_NAME == messages.Update.MSG_NAME:
|
||||
elif msg.type == BGP_MSG_UPDATE:
|
||||
assert self.state.bgp_state == const.BGP_FSM_ESTABLISHED
|
||||
# Will try to process this UDPATE message further
|
||||
self._handle_update_msg(msg)
|
||||
|
||||
elif msg.MSG_NAME == messages.RouteRefresh.MSG_NAME:
|
||||
elif msg.type == BGP_MSG_ROUTE_REFRESH:
|
||||
# If its route-refresh message
|
||||
assert self.state.bgp_state == const.BGP_FSM_ESTABLISHED
|
||||
self._handle_route_refresh_msg(msg)
|
||||
@ -1456,7 +1496,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# nothing is done inside peer, so should not see them here.
|
||||
raise ValueError('Peer does not support handling of %s'
|
||||
' message during % state' %
|
||||
(msg.MSG_NAME, self.state.bgp_state()))
|
||||
(msg, self.state.bgp_state()))
|
||||
|
||||
def _handle_err_sor_msg(self, afi, safi):
|
||||
# Check if ERR capability is enabled for this peer.
|
||||
@ -1474,7 +1514,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
if rst != 0:
|
||||
# Set a timer to clean the stale paths at configured time.
|
||||
# Clean/track inconsistent/stale routes.
|
||||
route_family = nlri.get_rf(afi, safi)
|
||||
route_family = RouteFamily(afi, safi)
|
||||
if route_family in SUPPORTED_GLOBAL_RF:
|
||||
self._refresh_stalepath_timer = self._spawn_after(
|
||||
'err-refresh-stale-path-timer', rst,
|
||||
@ -1498,7 +1538,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
# If this is end of RIB (EOR) message.
|
||||
elif demarcation == 2:
|
||||
# Clean/track inconsistent/stale routes.
|
||||
route_family = nlri.get_rf(afi, safi)
|
||||
route_family = RouteFamily(afi, safi)
|
||||
if route_family in SUPPORTED_GLOBAL_RF:
|
||||
tm = self._core_service.table_manager
|
||||
tm.clean_stale_routes(self, route_family)
|
||||
@ -1508,7 +1548,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
demarcation)
|
||||
|
||||
def _handle_route_refresh_req(self, afi, safi):
|
||||
rr_af = nlri.get_rf(afi, safi)
|
||||
rr_af = RouteFamily(afi, safi)
|
||||
self.state.incr(PeerCounterNames.RECV_REFRESH)
|
||||
|
||||
# Check if peer has asked for route-refresh for af that was advertised
|
||||
@ -1524,7 +1564,9 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
sor = None
|
||||
if self._protocol.is_enhanced_rr_cap_valid():
|
||||
# If enhanced route-refresh is valid/enabled, enqueue SOR.
|
||||
sor = messages.RouteRefresh(af, demarcation=1)
|
||||
afi = af.afi
|
||||
safi = af.safi
|
||||
sor = BGPRouteRefresh(afi, safi, reserved=1)
|
||||
self.enque_first_outgoing_msg(sor)
|
||||
|
||||
# Ask core to re-send sent routes
|
||||
@ -1539,7 +1581,9 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
sent.
|
||||
"""
|
||||
if self._protocol.is_enhanced_rr_cap_valid() and not sor.eor_sent:
|
||||
eor = messages.RouteRefresh(sor.route_family, demarcation=2)
|
||||
afi = sor.route_family.afi
|
||||
safi = sor.route_family.safi
|
||||
eor = BGPRouteRefresh(afi, safi, reserved=2)
|
||||
self.enque_outgoing_msg(eor)
|
||||
sor.eor_sent = True
|
||||
|
||||
@ -1589,7 +1633,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
def _enqueue_init_updates(self):
|
||||
"""Enqueues current routes to be shared with this peer."""
|
||||
assert self.state.bgp_state == const.BGP_FSM_ESTABLISHED
|
||||
if self.is_mbgp_cap_valid(nlri.RF_RTC_UC):
|
||||
if self.is_mbgp_cap_valid(RF_RTC_UC):
|
||||
# Enqueues all best-RTC_NLRIs to be sent as initial update to this
|
||||
# peer.
|
||||
self._peer_manager.comm_all_rt_nlris(self)
|
||||
@ -1610,7 +1654,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
' 1/132')
|
||||
# We will enqueue best path from all global destination.
|
||||
for route_family, table in global_tables.iteritems():
|
||||
if route_family == nlri.RF_RTC_UC:
|
||||
if route_family == RF_RTC_UC:
|
||||
continue
|
||||
if self.is_mbgp_cap_valid(route_family):
|
||||
for dest in table.itervalues():
|
||||
@ -1643,8 +1687,8 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
|
||||
# If RTC capability is available and path afi/saif is other than RT
|
||||
# nlri
|
||||
if path_rf != nlri.RF_RTC_UC and \
|
||||
self.is_mpbgp_cap_valid(nlri.RF_RTC_UC):
|
||||
if path_rf != RF_RTC_UC and \
|
||||
self.is_mpbgp_cap_valid(RF_RTC_UC):
|
||||
rtfilter = self._peer_manager.curr_peer_rtfilter(self)
|
||||
# If peer does not have any rtfilter or if rtfilter does not have
|
||||
# any RTs common with path RTs we do not share this path with the
|
||||
@ -1657,14 +1701,14 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
|
||||
# Transmit side loop detection: We check if leftmost AS matches
|
||||
# peers AS, if so we do not send UPDATE message to this peer.
|
||||
as_path = path.get_pattr(pathattr.AsPath.ATTR_NAME)
|
||||
as_path = path.get_pattr(BGP_ATTR_TYPE_AS_PATH)
|
||||
if as_path and as_path.has_matching_leftmost(self.remote_as):
|
||||
LOG.debug('Skipping sending path as AS_PATH has peer AS %s' %
|
||||
self.remote_as)
|
||||
return
|
||||
|
||||
if self._neigh_conf.multi_exit_disc:
|
||||
med_attr = path.get_pattr(pathattr.Med.ATTR_NAME)
|
||||
med_attr = path.get_pattr(BGP_ATTR_TYPE_MULTI_EXIT_DISC)
|
||||
if not med_attr:
|
||||
path = bgp_utils.clone_path_and_update_med_for_target_neighbor(
|
||||
path,
|
||||
@ -1675,10 +1719,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
if path.source is None:
|
||||
# Construct OutgoingRoute specific for this peer and put it in
|
||||
# its sink.
|
||||
bgp4_format = False
|
||||
if self._neigh_conf.cap_mbgp_ipv4:
|
||||
bgp4_format = True
|
||||
outgoing_route = OutgoingRoute(path, bgp4_format=bgp4_format)
|
||||
outgoing_route = OutgoingRoute(path)
|
||||
self.enque_outgoing_msg(outgoing_route)
|
||||
|
||||
# If path from a bgp-peer is new best path, we share it with
|
||||
@ -1698,10 +1739,10 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
|
||||
# If new best path has community attribute, it should be taken into
|
||||
# account when sending UPDATE to peers.
|
||||
comm_attr = path.get_pattr(pathattr.Community.ATTR_NAME)
|
||||
comm_attr = path.get_pattr(BGP_ATTR_TYPE_COMMUNITIES)
|
||||
if comm_attr:
|
||||
comm_attr_na = comm_attr.has_comm_attr(
|
||||
pathattr.Community.NO_ADVERTISE
|
||||
BGPPathAttributeCommunities.NO_ADVERTISE
|
||||
)
|
||||
# If we have NO_ADVERTISE attribute present, we do not send
|
||||
# UPDATE to any peers
|
||||
@ -1712,10 +1753,11 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
||||
return
|
||||
|
||||
comm_attr_ne = comm_attr.has_comm_attr(
|
||||
pathattr.Community.NO_EXPORT
|
||||
BGPPathAttributeCommunities.NO_EXPORT
|
||||
)
|
||||
comm_attr_nes = comm_attr.has_comm_attr(
|
||||
pathattr.Community.NO_EXPORT_SUBCONFED)
|
||||
BGPPathAttributeCommunities.NO_EXPORT_SUBCONFED
|
||||
)
|
||||
# If NO_EXPORT_SUBCONFED/NO_EXPORT is one of the attribute, we
|
||||
# do not advertise to eBGP peers as we do not have any
|
||||
# confederation feature at this time.
|
||||
|
||||
@ -18,12 +18,6 @@
|
||||
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_RTC_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import AsPath
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import LocalPref
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import Med
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import Origin
|
||||
|
||||
from ryu.services.protocols.bgp.base import Activity
|
||||
from ryu.services.protocols.bgp.base import add_bgp_error_metadata
|
||||
from ryu.services.protocols.bgp.base import BGP_PROCESSOR_ERROR_CODE
|
||||
@ -31,6 +25,14 @@ from ryu.services.protocols.bgp.base import BGPSException
|
||||
from ryu.services.protocols.bgp.utils import circlist
|
||||
from ryu.services.protocols.bgp.utils.evtlet import EventletIOFactory
|
||||
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_LOCAL_PREF
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MULTI_EXIT_DISC
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_IGP
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_EGP
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_INCOMPLETE
|
||||
|
||||
LOG = logging.getLogger('bgpspeaker.processor')
|
||||
|
||||
@ -150,9 +152,9 @@ class BgpProcessor(Activity):
|
||||
# Wake-up processing thread if sleeping.
|
||||
self.dest_que_evt.set()
|
||||
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
# Best path computation related utilities.
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
|
||||
# Various reasons a path is chosen as best path.
|
||||
BPR_UNKNOWN = 'Unknown'
|
||||
@ -289,8 +291,8 @@ def _cmp_by_local_pref(path1, path2):
|
||||
# TODO(PH): Revisit this when BGPS has concept of policy to be applied to
|
||||
# in-bound NLRIs.
|
||||
# Default local-pref values is 100
|
||||
lp1 = path1.get_pattr(LocalPref.ATTR_NAME)
|
||||
lp2 = path2.get_pattr(LocalPref.ATTR_NAME)
|
||||
lp1 = path1.get_pattr(BGP_ATTR_TYPE_LOCAL_PREF)
|
||||
lp2 = path2.get_pattr(BGP_ATTR_TYPE_LOCAL_PREF)
|
||||
if not (lp1 and lp2):
|
||||
return None
|
||||
|
||||
@ -335,8 +337,8 @@ def _cmp_by_aspath(path1, path2):
|
||||
Shortest as-path length is preferred. If both path have same lengths,
|
||||
we return None.
|
||||
"""
|
||||
as_path1 = path1.get_pattr(AsPath.ATTR_NAME)
|
||||
as_path2 = path2.get_pattr(AsPath.ATTR_NAME)
|
||||
as_path1 = path1.get_pattr(BGP_ATTR_TYPE_AS_PATH)
|
||||
as_path2 = path2.get_pattr(BGP_ATTR_TYPE_AS_PATH)
|
||||
assert as_path1 and as_path2
|
||||
l1 = as_path1.get_as_path_len()
|
||||
l2 = as_path2.get_as_path_len()
|
||||
@ -356,18 +358,18 @@ def _cmp_by_origin(path1, path2):
|
||||
If both paths have same origin, we return None.
|
||||
"""
|
||||
def get_origin_pref(origin):
|
||||
if origin.value == Origin.IGP:
|
||||
if origin.value == BGP_ATTR_ORIGIN_IGP:
|
||||
return 3
|
||||
elif origin.value == Origin.EGP:
|
||||
elif origin.value == BGP_ATTR_ORIGIN_EGP:
|
||||
return 2
|
||||
elif origin.value == Origin.INCOMPLETE:
|
||||
elif origin.value == BGP_ATTR_ORIGIN_INCOMPLETE:
|
||||
return 1
|
||||
else:
|
||||
LOG.error('Invalid origin value encountered %s.' % origin)
|
||||
return 0
|
||||
|
||||
origin1 = path1.get_pattr(Origin.ATTR_NAME)
|
||||
origin2 = path2.get_pattr(Origin.ATTR_NAME)
|
||||
origin1 = path1.get_pattr(BGP_ATTR_TYPE_ORIGIN)
|
||||
origin2 = path2.get_pattr(BGP_ATTR_TYPE_ORIGIN)
|
||||
assert origin1 is not None and origin2 is not None
|
||||
|
||||
# If both paths have same origins
|
||||
@ -394,7 +396,7 @@ def _cmp_by_med(path1, path2):
|
||||
RFC says lower MED is preferred over higher MED value.
|
||||
"""
|
||||
def get_path_med(path):
|
||||
med = path.get_pattr(Med.ATTR_NAME)
|
||||
med = path.get_pattr(BGP_ATTR_TYPE_MULTI_EXIT_DISC)
|
||||
if not med:
|
||||
return 0
|
||||
return med.value
|
||||
|
||||
@ -28,8 +28,6 @@ from ryu.services.protocols.bgp.base import BGPSException
|
||||
from ryu.services.protocols.bgp.base import get_validator
|
||||
from ryu.services.protocols.bgp.base import RUNTIME_CONF_ERROR_CODE
|
||||
from ryu.services.protocols.bgp.base import validate
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import ExtCommunity
|
||||
from ryu.services.protocols.bgp.utils import validation
|
||||
from ryu.services.protocols.bgp.utils.validation import is_valid_old_asn
|
||||
|
||||
@ -73,9 +71,9 @@ MAX_NUM_EXPORT_RT = 250
|
||||
MAX_NUM_SOO = 10
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
# Runtime configuration errors or exceptions.
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
|
||||
@add_bgp_error_metadata(code=RUNTIME_CONF_ERROR_CODE, sub_code=1,
|
||||
def_desc='Error with runtime-configuration.')
|
||||
@ -139,9 +137,9 @@ class ConfigValueError(RuntimeConfigError):
|
||||
super(ConfigValueError, self).__init__(desc=kwargs.get('desc'))
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
# Configuration base classes.
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
|
||||
class BaseConf(object):
|
||||
"""Base class for a set of configuration values.
|
||||
@ -225,8 +223,8 @@ class BaseConf(object):
|
||||
self._settings[req_attr] = req_attr_value
|
||||
|
||||
def add_listener(self, evt, callback):
|
||||
# if (evt not in self.get_valid_evts()):
|
||||
# raise RuntimeConfigError(desc=('Unknown event %s' % evt))
|
||||
# if (evt not in self.get_valid_evts()):
|
||||
# raise RuntimeConfigError(desc=('Unknown event %s' % evt))
|
||||
|
||||
listeners = self._listeners.get(evt, None)
|
||||
if not listeners:
|
||||
@ -523,9 +521,9 @@ class ConfEvent(object):
|
||||
(self.src, self.name, self.value))
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
# Runtime configuration setting validators and their registry.
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
|
||||
@validate(name=ConfWithId.ID)
|
||||
def validate_conf_id(identifier):
|
||||
@ -658,9 +656,7 @@ def validate_soo_list(soo_list):
|
||||
if not (len(soo_list) <= MAX_NUM_SOO):
|
||||
raise ConfigValueError(desc='Max. SOO is limited to %s' %
|
||||
MAX_NUM_SOO)
|
||||
try:
|
||||
ExtCommunity.validate_supported_attributes(soo_list)
|
||||
except ValueError:
|
||||
if not all(validation.is_valid_ext_comm_attr(attr) for attr in soo_list):
|
||||
raise ConfigValueError(conf_name=SITE_OF_ORIGINS,
|
||||
conf_value=soo_list)
|
||||
# Check if we have duplicates
|
||||
@ -691,9 +687,9 @@ def validate_advertise_peer_as(advertise_peer_as):
|
||||
return advertise_peer_as
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
# Other utils.
|
||||
#==============================================================================
|
||||
# =============================================================================
|
||||
|
||||
def compute_optional_conf(conf_name, default_value, **all_config):
|
||||
"""Returns *conf_name* settings if provided in *all_config*, else returns
|
||||
|
||||
@ -229,9 +229,9 @@ class CommonConf(BaseConf):
|
||||
MAX_PATH_EXT_RTFILTER_ALL, DEFAULT_MAX_PATH_EXT_RTFILTER_ALL,
|
||||
**kwargs)
|
||||
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
# Required attributes
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
|
||||
@property
|
||||
def local_as(self):
|
||||
@ -241,9 +241,9 @@ class CommonConf(BaseConf):
|
||||
def router_id(self):
|
||||
return self._settings[ROUTER_ID]
|
||||
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
# Optional attributes with valid defaults.
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
|
||||
@property
|
||||
def bgp_conn_retry_time(self):
|
||||
|
||||
@ -19,6 +19,18 @@
|
||||
from abc import abstractmethod
|
||||
import logging
|
||||
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv6_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
from ryu.lib.packet.bgp import BGPOptParamCapabilityEnhancedRouteRefresh
|
||||
from ryu.lib.packet.bgp import BGPOptParamCapabilityMultiprotocol
|
||||
from ryu.lib.packet.bgp import BGPOptParamCapabilityRouteRefresh
|
||||
from ryu.lib.packet.bgp import BGP_CAP_ENHANCED_ROUTE_REFRESH
|
||||
from ryu.lib.packet.bgp import BGP_CAP_MULTIPROTOCOL
|
||||
from ryu.lib.packet.bgp import BGP_CAP_ROUTE_REFRESH
|
||||
|
||||
from ryu.services.protocols.bgp.base import OrderedDict
|
||||
from ryu.services.protocols.bgp.rtconf.base import ADVERTISE_PEER_AS
|
||||
from ryu.services.protocols.bgp.rtconf.base import BaseConf
|
||||
@ -45,17 +57,6 @@ from ryu.services.protocols.bgp.rtconf.base import SITE_OF_ORIGINS
|
||||
from ryu.services.protocols.bgp.rtconf.base import validate
|
||||
from ryu.services.protocols.bgp.rtconf.base import validate_med
|
||||
from ryu.services.protocols.bgp.rtconf.base import validate_soo_list
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.capabilities import \
|
||||
EnhancedRouteRefreshCap
|
||||
from ryu.services.protocols.bgp.protocols.bgp.capabilities import \
|
||||
MultiprotocolExtentionCap
|
||||
from ryu.services.protocols.bgp.protocols.bgp.capabilities import \
|
||||
RouteRefreshCap
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_VPN
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv6_VPN
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_RTC_UC
|
||||
from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4
|
||||
from ryu.services.protocols.bgp.utils.validation import is_valid_old_asn
|
||||
|
||||
@ -224,9 +225,9 @@ class NeighborConf(ConfWithId, ConfWithStats):
|
||||
self_valid_evts.update(NeighborConf.VALID_EVT)
|
||||
return self_valid_evts
|
||||
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
# Required attributes
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
|
||||
@property
|
||||
def remote_as(self):
|
||||
@ -244,9 +245,9 @@ class NeighborConf(ConfWithId, ConfWithStats):
|
||||
def host_bind_port(self):
|
||||
return self._settings[LOCAL_PORT]
|
||||
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
# Optional attributes with valid defaults.
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
|
||||
@property
|
||||
def hold_time(self):
|
||||
@ -288,9 +289,9 @@ class NeighborConf(ConfWithId, ConfWithStats):
|
||||
self._notify_listeners(NeighborConf.UPDATE_ENABLED_EVT,
|
||||
enable)
|
||||
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
# Optional attributes with no valid defaults.
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
|
||||
@property
|
||||
def multi_exit_disc(self):
|
||||
@ -334,27 +335,35 @@ class NeighborConf(ConfWithId, ConfWithStats):
|
||||
capabilities = OrderedDict()
|
||||
mbgp_caps = []
|
||||
if self.cap_mbgp_ipv4:
|
||||
mbgp_caps.append(MultiprotocolExtentionCap(RF_IPv4_UC))
|
||||
mbgp_caps.append(
|
||||
BGPOptParamCapabilityMultiprotocol(
|
||||
RF_IPv4_UC.afi, RF_IPv4_UC.safi))
|
||||
|
||||
if self.cap_mbgp_vpnv4:
|
||||
mbgp_caps.append(MultiprotocolExtentionCap(RF_IPv4_VPN))
|
||||
mbgp_caps.append(
|
||||
BGPOptParamCapabilityMultiprotocol(
|
||||
RF_IPv4_VPN.afi, RF_IPv4_VPN.safi))
|
||||
|
||||
if self.cap_mbgp_vpnv6:
|
||||
mbgp_caps.append(MultiprotocolExtentionCap(RF_IPv6_VPN))
|
||||
mbgp_caps.append(
|
||||
BGPOptParamCapabilityMultiprotocol(
|
||||
RF_IPv6_VPN.afi, RF_IPv6_VPN.safi))
|
||||
|
||||
if self.cap_rtc:
|
||||
mbgp_caps.append(MultiprotocolExtentionCap(RF_RTC_UC))
|
||||
mbgp_caps.append(
|
||||
BGPOptParamCapabilityMultiprotocol(
|
||||
RF_RTC_UC.afi, RF_RTC_UC.safi))
|
||||
|
||||
if mbgp_caps:
|
||||
capabilities[MultiprotocolExtentionCap.CODE] = mbgp_caps
|
||||
capabilities[BGP_CAP_MULTIPROTOCOL] = mbgp_caps
|
||||
|
||||
if self.cap_refresh:
|
||||
capabilities[RouteRefreshCap.CODE] = [
|
||||
RouteRefreshCap.get_singleton()]
|
||||
capabilities[BGP_CAP_ROUTE_REFRESH] = [
|
||||
BGPOptParamCapabilityRouteRefresh()]
|
||||
|
||||
if self.cap_enhanced_refresh:
|
||||
capabilities[EnhancedRouteRefreshCap.CODE] = [
|
||||
EnhancedRouteRefreshCap.get_singleton()]
|
||||
capabilities[BGP_CAP_ENHANCED_ROUTE_REFRESH] = [
|
||||
BGPOptParamCapabilityEnhancedRouteRefresh()]
|
||||
|
||||
return capabilities
|
||||
|
||||
|
||||
@ -20,9 +20,11 @@
|
||||
import abc
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import ExtCommunity
|
||||
from ryu.services.protocols.bgp.utils import validation
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv6_UC
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeExtendedCommunities
|
||||
|
||||
from ryu.services.protocols.bgp.utils import validation
|
||||
from ryu.services.protocols.bgp.base import get_validator
|
||||
from ryu.services.protocols.bgp.rtconf.base import BaseConf
|
||||
from ryu.services.protocols.bgp.rtconf.base import BaseConfListener
|
||||
@ -40,8 +42,6 @@ from ryu.services.protocols.bgp.rtconf.base import SITE_OF_ORIGINS
|
||||
from ryu.services.protocols.bgp.rtconf.base import validate
|
||||
from ryu.services.protocols.bgp.rtconf.base import validate_med
|
||||
from ryu.services.protocols.bgp.rtconf.base import validate_soo_list
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv6_UC
|
||||
|
||||
|
||||
LOG = logging.getLogger('bgpspeaker.rtconf.vrfs')
|
||||
@ -73,11 +73,8 @@ def validate_import_rts(import_rts):
|
||||
if not (len(import_rts) <= MAX_NUM_IMPORT_RT):
|
||||
raise ConfigValueError(desc='Max. import RT is limited to %s' %
|
||||
MAX_NUM_IMPORT_RT)
|
||||
try:
|
||||
ExtCommunity.validate_supported_attributes(import_rts)
|
||||
except ValueError:
|
||||
raise ConfigValueError(conf_name=IMPORT_RTS,
|
||||
conf_value=import_rts)
|
||||
if not all(validation.is_valid_ext_comm_attr(rt) for rt in import_rts):
|
||||
raise ConfigValueError(conf_name=IMPORT_RTS, conf_value=import_rts)
|
||||
# Check if we have duplicates
|
||||
unique_rts = set(import_rts)
|
||||
if len(unique_rts) != len(import_rts):
|
||||
@ -94,9 +91,8 @@ def validate_export_rts(export_rts):
|
||||
if not (len(export_rts) <= MAX_NUM_EXPORT_RT):
|
||||
raise ConfigValueError(desc='Max. import RT is limited to %s' %
|
||||
MAX_NUM_EXPORT_RT)
|
||||
try:
|
||||
ExtCommunity.validate_supported_attributes(export_rts)
|
||||
except Exception:
|
||||
|
||||
if not all(validation.is_valid_ext_comm_attr(rt) for rt in export_rts):
|
||||
raise ConfigValueError(conf_name=EXPORT_RTS, conf_value=export_rts)
|
||||
# Check if we have duplicates
|
||||
unique_rts = set(export_rts)
|
||||
@ -169,17 +165,17 @@ class VrfConf(ConfWithId, ConfWithStats):
|
||||
import_maps = kwargs.pop(IMPORT_MAPS, [])
|
||||
self._settings[IMPORT_MAPS] = import_maps
|
||||
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
# Required attributes
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
|
||||
@property
|
||||
def route_dist(self):
|
||||
return self._settings[ROUTE_DISTINGUISHER]
|
||||
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
# Optional attributes with valid defaults.
|
||||
#==========================================================================
|
||||
# =========================================================================
|
||||
|
||||
@property
|
||||
def import_rts(self):
|
||||
|
||||
@ -21,6 +21,24 @@ import socket
|
||||
import struct
|
||||
import traceback
|
||||
|
||||
from ryu.lib.packet import bgp
|
||||
from ryu.lib.packet.bgp import RouteFamily
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
from ryu.lib.packet.bgp import BGPMessage
|
||||
from ryu.lib.packet.bgp import BGPOpen
|
||||
from ryu.lib.packet.bgp import BGPUpdate
|
||||
from ryu.lib.packet.bgp import BGPKeepAlive
|
||||
from ryu.lib.packet.bgp import BGPNotification
|
||||
from ryu.lib.packet.bgp import BGPRouteRefresh
|
||||
from ryu.lib.packet.bgp import BGP_MSG_OPEN
|
||||
from ryu.lib.packet.bgp import BGP_MSG_UPDATE
|
||||
from ryu.lib.packet.bgp import BGP_MSG_KEEPALIVE
|
||||
from ryu.lib.packet.bgp import BGP_MSG_NOTIFICATION
|
||||
from ryu.lib.packet.bgp import BGP_MSG_ROUTE_REFRESH
|
||||
from ryu.lib.packet.bgp import BGP_CAP_ENHANCED_ROUTE_REFRESH
|
||||
from ryu.lib.packet.bgp import BGP_CAP_MULTIPROTOCOL
|
||||
from ryu.lib.packet.bgp import BGP_CAP_ROUTE_REFRESH
|
||||
|
||||
from ryu.services.protocols.bgp.base import Activity
|
||||
from ryu.services.protocols.bgp.base import add_bgp_error_metadata
|
||||
from ryu.services.protocols.bgp.base import BGPSException
|
||||
@ -30,25 +48,8 @@ from ryu.services.protocols.bgp.constants import BGP_FSM_OPEN_CONFIRM
|
||||
from ryu.services.protocols.bgp.constants import BGP_FSM_OPEN_SENT
|
||||
from ryu.services.protocols.bgp.constants import BGP_VERSION_NUM
|
||||
from ryu.services.protocols.bgp.protocol import Protocol
|
||||
from ryu.services.protocols.bgp.protocols.bgp.capabilities import \
|
||||
EnhancedRouteRefreshCap
|
||||
from ryu.services.protocols.bgp.protocols.bgp.capabilities import \
|
||||
MultiprotocolExtentionCap
|
||||
from ryu.services.protocols.bgp.protocols.bgp.capabilities import \
|
||||
RouteRefreshCap
|
||||
import ryu.services.protocols.bgp.protocols.bgp.exceptions as exceptions
|
||||
from ryu.services.protocols.bgp.protocols.bgp.exceptions import BgpExc
|
||||
from ryu.services.protocols.bgp.protocols.bgp import messages
|
||||
from ryu.services.protocols.bgp.protocols.bgp.messages import Keepalive
|
||||
from ryu.services.protocols.bgp.protocols.bgp.messages import Notification
|
||||
from ryu.services.protocols.bgp.protocols.bgp.messages import Open
|
||||
from ryu.services.protocols.bgp.protocols.bgp.messages import RouteRefresh
|
||||
from ryu.services.protocols.bgp.protocols.bgp.messages import Update
|
||||
from ryu.services.protocols.bgp.protocols.bgp import nlri
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_RTC_UC
|
||||
from ryu.services.protocols.bgp.utils.validation import is_valid_old_asn
|
||||
|
||||
|
||||
LOG = logging.getLogger('bgpspeaker.speaker')
|
||||
|
||||
# BGP min. and max. message lengths as per RFC.
|
||||
@ -56,7 +57,7 @@ BGP_MIN_MSG_LEN = 19
|
||||
BGP_MAX_MSG_LEN = 4096
|
||||
|
||||
# Keep-alive singleton.
|
||||
_KEEP_ALIVE = Keepalive()
|
||||
_KEEP_ALIVE = BGPKeepAlive()
|
||||
|
||||
|
||||
@add_bgp_error_metadata(code=CORE_ERROR_CODE, sub_code=2,
|
||||
@ -74,11 +75,11 @@ def nofitication_factory(code, subcode):
|
||||
- `code`: (int) BGP error code
|
||||
- `subcode`: (int) BGP error sub-code
|
||||
"""
|
||||
reason = Notification.REASONS.get((code, subcode))
|
||||
if not reason:
|
||||
notification = BGPNotification(code, subcode)
|
||||
if not notification.reason:
|
||||
raise ValueError('Invalid code/sub-code.')
|
||||
|
||||
return Notification(code, subcode)
|
||||
return notification
|
||||
|
||||
|
||||
class BgpProtocol(Protocol, Activity):
|
||||
@ -174,8 +175,8 @@ class BgpProtocol(Protocol, Activity):
|
||||
peer_cap = self.recv_open_msg.caps
|
||||
# Both local and peer should advertise ERR capability for it to be
|
||||
# enabled.
|
||||
if (local_cap.get(EnhancedRouteRefreshCap.CODE) and
|
||||
peer_cap.get(EnhancedRouteRefreshCap.CODE)):
|
||||
if (local_cap.get(BGP_CAP_ENHANCED_ROUTE_REFRESH) and
|
||||
peer_cap.get(BGP_CAP_ENHANCED_ROUTE_REFRESH)):
|
||||
err_cap_enabled = True
|
||||
|
||||
return err_cap_enabled
|
||||
@ -183,14 +184,13 @@ class BgpProtocol(Protocol, Activity):
|
||||
def _check_route_fmly_adv(self, open_msg, route_family):
|
||||
match_found = False
|
||||
|
||||
local_caps = open_msg.caps
|
||||
mbgp_cap = local_caps.get(MultiprotocolExtentionCap.CODE)
|
||||
# Check MP_BGP capability was advertised.
|
||||
if mbgp_cap:
|
||||
# Iterate over all advertised mp_bgp caps to find a match.
|
||||
for peer_cap in mbgp_cap:
|
||||
if (route_family.afi == peer_cap.route_family.afi and
|
||||
route_family.safi == peer_cap.route_family.safi):
|
||||
local_caps = open_msg.opt_param
|
||||
for cap in local_caps:
|
||||
# Check MP_BGP capability was advertised.
|
||||
if cap.cap_code == BGP_CAP_MULTIPROTOCOL:
|
||||
# Iterate over all advertised mp_bgp caps to find a match.
|
||||
if (route_family.afi == cap.afi and
|
||||
route_family.safi == cap.safi):
|
||||
match_found = True
|
||||
|
||||
return match_found
|
||||
@ -218,8 +218,8 @@ class BgpProtocol(Protocol, Activity):
|
||||
local_caps = self.sent_open_msg.caps
|
||||
remote_caps = self.recv_open_msg.caps
|
||||
|
||||
local_mbgp_cap = local_caps.get(MultiprotocolExtentionCap.CODE)
|
||||
remote_mbgp_cap = remote_caps.get(MultiprotocolExtentionCap.CODE)
|
||||
local_mbgp_cap = local_caps.get(BGP_CAP_MULTIPROTOCOL)
|
||||
remote_mbgp_cap = remote_caps.get(BGP_CAP_MULTIPROTOCOL)
|
||||
# Check MP_BGP capabilities were advertised.
|
||||
if local_mbgp_cap and remote_mbgp_cap:
|
||||
local_families = {
|
||||
@ -236,7 +236,7 @@ class BgpProtocol(Protocol, Activity):
|
||||
|
||||
afs = []
|
||||
for afi, safi in afi_safi:
|
||||
afs.append(nlri.get_rf(afi, safi))
|
||||
afs.append(RouteFamily(afi, safi))
|
||||
return afs
|
||||
|
||||
def is_mbgp_cap_valid(self, route_family):
|
||||
@ -262,7 +262,7 @@ class BgpProtocol(Protocol, Activity):
|
||||
def data_received(self, next_bytes):
|
||||
try:
|
||||
self._data_received(next_bytes)
|
||||
except BgpExc as exc:
|
||||
except bgp.BgpExc as exc:
|
||||
LOG.error(
|
||||
"BGPExc Exception while receiving data: "
|
||||
"%s \n Traceback %s \n"
|
||||
@ -310,7 +310,7 @@ class BgpProtocol(Protocol, Activity):
|
||||
# authentication.
|
||||
if (auth != BgpProtocol.MESSAGE_MARKER):
|
||||
LOG.error('Invalid message marker received: %s' % auth)
|
||||
raise exceptions.NotSync()
|
||||
raise bgp.NotSync()
|
||||
|
||||
# Check if we have valid bgp message length.
|
||||
check = lambda: length < BGP_MIN_MSG_LEN\
|
||||
@ -318,36 +318,27 @@ class BgpProtocol(Protocol, Activity):
|
||||
|
||||
# RFC says: The minimum length of the OPEN message is 29
|
||||
# octets (including the message header).
|
||||
check2 = lambda: ptype == Open.TYPE_CODE\
|
||||
and length < Open.MIN_LENGTH
|
||||
check2 = lambda: ptype == BGP_MSG_OPEN\
|
||||
and length < BGPOpen._MIN_LEN
|
||||
|
||||
# RFC says: A KEEPALIVE message consists of only the
|
||||
# message header and has a length of 19 octets.
|
||||
check3 = lambda: ptype == Keepalive.TYPE_CODE\
|
||||
and length != BGP_MIN_MSG_LEN
|
||||
check3 = lambda: ptype == BGP_MSG_KEEPALIVE\
|
||||
and length != BGPKeepAlive._MIN_LEN
|
||||
|
||||
# RFC says: The minimum length of the UPDATE message is 23
|
||||
# octets.
|
||||
check4 = lambda: ptype == Update.TYPE_CODE\
|
||||
and length < Update.MIN_LENGTH
|
||||
check4 = lambda: ptype == BGP_MSG_UPDATE\
|
||||
and length < BGPUpdate._MIN_LEN
|
||||
|
||||
if check() or check2() or check3() or check4():
|
||||
raise exceptions.BadLen(ptype, length)
|
||||
raise bgp.BadLen(ptype, length)
|
||||
|
||||
# If we have partial message we wait for rest of the message.
|
||||
if len(self._recv_buff) < length:
|
||||
return
|
||||
|
||||
# If we have full message, we get its payload/data.
|
||||
payload = self._recv_buff[BGP_MIN_MSG_LEN:length]
|
||||
|
||||
# Update buffer to not contain any part of the current message.
|
||||
self._recv_buff = self._recv_buff[length:]
|
||||
|
||||
# Try to decode payload into specified message type.
|
||||
# If we have any error parsing the message, we send appropriate
|
||||
# bgp notification message.
|
||||
msg = messages.decode(ptype, payload, length)
|
||||
msg, rest = BGPMessage.parser(self._recv_buff)
|
||||
self._recv_buff = rest
|
||||
|
||||
# If we have a valid bgp message we call message handler.
|
||||
self._handle_msg(msg)
|
||||
@ -365,14 +356,9 @@ class BgpProtocol(Protocol, Activity):
|
||||
RFC ref: http://tools.ietf.org/html/rfc4486
|
||||
http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml
|
||||
"""
|
||||
reason = Notification.REASONS.get((code, subcode))
|
||||
if not reason:
|
||||
# Not checking for type of parameters to allow some flexibility
|
||||
# via. duck-typing.
|
||||
raise ValueError('Unsupported code/sub-code given.')
|
||||
|
||||
notification = Notification(code, subcode, reason)
|
||||
self._socket.sendall(notification.encode())
|
||||
notification = BGPNotification(code, subcode)
|
||||
reason = notification.reason
|
||||
self._socket.sendall(notification.serialize())
|
||||
self._signal_bus.bgp_error(self._peer, code, subcode, reason)
|
||||
LOG.error(
|
||||
'Sent notification to %r>> %s' %
|
||||
@ -385,8 +371,8 @@ class BgpProtocol(Protocol, Activity):
|
||||
raise BgpProtocolException('Tried to send message to peer when '
|
||||
'this protocol instance is not started'
|
||||
' or is no longer is started state.')
|
||||
self._socket.sendall(msg.encode())
|
||||
if msg.MSG_NAME == Notification.MSG_NAME:
|
||||
self._socket.sendall(msg.serialize())
|
||||
if msg.type == BGP_MSG_NOTIFICATION:
|
||||
LOG.error('Sent notification to %s>> %s' %
|
||||
(self.get_peername(), msg))
|
||||
|
||||
@ -394,7 +380,7 @@ class BgpProtocol(Protocol, Activity):
|
||||
|
||||
else:
|
||||
LOG.debug('Sent msg. %s to %s>> %s' %
|
||||
(msg.MSG_NAME, self.get_peername(), msg))
|
||||
(msg.__class__, self.get_peername(), msg))
|
||||
|
||||
def stop(self):
|
||||
Activity.stop(self)
|
||||
@ -407,28 +393,31 @@ class BgpProtocol(Protocol, Activity):
|
||||
settings. RTC or RR/ERR are MUST capability if peer does not support
|
||||
either one of them we have to end session.
|
||||
"""
|
||||
assert open_msg.TYPE_CODE == Open.TYPE_CODE
|
||||
assert open_msg.type == BGP_MSG_OPEN
|
||||
# Validate remote ASN.
|
||||
remote_asnum = open_msg.asnum
|
||||
remote_asnum = open_msg.my_as
|
||||
# Since 4byte AS is not yet supported, we validate AS as old style AS.
|
||||
if (not is_valid_old_asn(remote_asnum) or
|
||||
remote_asnum != self._peer.remote_as):
|
||||
raise exceptions.BadPeerAs()
|
||||
raise bgp.BadPeerAs()
|
||||
|
||||
# Validate bgp version number.
|
||||
if open_msg.version != BGP_VERSION_NUM:
|
||||
raise exceptions.UnsupportedVersion(BGP_VERSION_NUM)
|
||||
raise bgp.UnsupportedVersion(BGP_VERSION_NUM)
|
||||
|
||||
adv_caps = open_msg.caps
|
||||
rr_cap_adv = adv_caps.get(RouteRefreshCap.CODE)
|
||||
err_cap_adv = adv_caps.get(EnhancedRouteRefreshCap.CODE)
|
||||
adv_caps = open_msg.opt_param
|
||||
for cap in adv_caps:
|
||||
if cap.cap_code == BGP_CAP_ROUTE_REFRESH:
|
||||
rr_cap_adv = cap
|
||||
elif cap.cap_code == BGP_CAP_ENHANCED_ROUTE_REFRESH:
|
||||
err_cap_adv = cap
|
||||
# If either RTC or RR/ERR are MUST capability if peer does not support
|
||||
# either one of them we have to end session as we have to request peer
|
||||
# to send prefixes for new VPNs that may be created automatically.
|
||||
# TODO(PH): Check with experts if error is suitable in this case
|
||||
if not (rr_cap_adv or err_cap_adv or
|
||||
self._check_route_fmly_adv(open_msg, RF_RTC_UC)):
|
||||
raise exceptions.UnsupportedOptParam()
|
||||
raise bgp.UnsupportedOptParam()
|
||||
|
||||
def _handle_msg(self, msg):
|
||||
"""When a BGP message is received, send it to peer.
|
||||
@ -438,10 +427,10 @@ class BgpProtocol(Protocol, Activity):
|
||||
*Notification* message we close connection with peer.
|
||||
"""
|
||||
LOG.debug('Received %s msg. from %s<< \n%s' %
|
||||
(msg.MSG_NAME, str(self.get_peername()), msg))
|
||||
(msg.__class__, str(self.get_peername()), msg))
|
||||
|
||||
# If we receive open message we try to bind to protocol
|
||||
if (msg.MSG_NAME == Open.MSG_NAME):
|
||||
if (msg.type == BGP_MSG_OPEN):
|
||||
if self.state == BGP_FSM_OPEN_SENT:
|
||||
# Validate open message.
|
||||
self._validate_open_msg(msg)
|
||||
@ -458,18 +447,18 @@ class BgpProtocol(Protocol, Activity):
|
||||
# resolution choose different instance of protocol and this
|
||||
# instance has to close. Before closing it sends
|
||||
# appropriate notification msg. to peer.
|
||||
raise exceptions.CollisionResolution()
|
||||
raise bgp.CollisionResolution()
|
||||
|
||||
# If peer sends Hold Time as zero, then according to RFC we do
|
||||
# not set Hold Time and Keep Alive timer.
|
||||
if msg.holdtime == 0:
|
||||
if msg.hold_time == 0:
|
||||
LOG.info('The Hold Time sent by the peer is zero, hence '
|
||||
'not setting any Hold Time and Keep Alive'
|
||||
' timers.')
|
||||
else:
|
||||
# Start Keep Alive timer considering Hold Time preference
|
||||
# of the peer.
|
||||
self._start_timers(msg.holdtime)
|
||||
self._start_timers(msg.hold_time)
|
||||
self._send_keepalive()
|
||||
|
||||
# Peer does not see open message.
|
||||
@ -480,8 +469,8 @@ class BgpProtocol(Protocol, Activity):
|
||||
'OpenSent')
|
||||
# Received out-of-order open message
|
||||
# We raise Finite state machine error
|
||||
raise exceptions.FiniteStateMachineError()
|
||||
elif msg.MSG_NAME == Notification.MSG_NAME:
|
||||
raise bgp.FiniteStateMachineError()
|
||||
elif msg.type == BGP_MSG_NOTIFICATION:
|
||||
if self._peer:
|
||||
self._signal_bus.bgp_notification_received(self._peer, msg)
|
||||
# If we receive notification message
|
||||
@ -491,14 +480,14 @@ class BgpProtocol(Protocol, Activity):
|
||||
return
|
||||
|
||||
# If we receive keepalive or update message, we reset expire timer.
|
||||
if (msg.MSG_NAME == Keepalive.MSG_NAME or
|
||||
msg.MSG_NAME == Update.MSG_NAME):
|
||||
if (msg.type == BGP_MSG_KEEPALIVE or
|
||||
msg.type == BGP_MSG_UPDATE):
|
||||
if self._expiry:
|
||||
self._expiry.reset()
|
||||
|
||||
# Call peer message handler for appropriate messages.
|
||||
if (msg.MSG_NAME in
|
||||
(Keepalive.MSG_NAME, Update.MSG_NAME, RouteRefresh.MSG_NAME)):
|
||||
if (msg.type in
|
||||
(BGP_MSG_UPDATE, BGP_MSG_KEEPALIVE, BGP_MSG_ROUTE_REFRESH)):
|
||||
self._peer.handle_msg(msg)
|
||||
# We give chance to other threads to run.
|
||||
self.pause(0)
|
||||
@ -529,8 +518,8 @@ class BgpProtocol(Protocol, Activity):
|
||||
"""Hold timer expired event handler.
|
||||
"""
|
||||
LOG.info('Negotiated hold time %s expired.' % self._holdtime)
|
||||
code = exceptions.HoldTimerExpired.CODE
|
||||
subcode = exceptions.HoldTimerExpired.SUB_CODE
|
||||
code = BGP_ERROR_HOLD_TIMER_EXPIRED
|
||||
subcode = BGP_ERROR_SUB_HOLD_TIMER_EXPIRED
|
||||
self.send_notification(code, subcode)
|
||||
self.connection_lost('Negotiated hold time %s expired.' %
|
||||
self._holdtime)
|
||||
@ -554,7 +543,7 @@ class BgpProtocol(Protocol, Activity):
|
||||
self.data_received(next_bytes)
|
||||
except socket.error as err:
|
||||
conn_lost_reason = 'Connection to peer lost: %s.' % err
|
||||
except BgpExc as ex:
|
||||
except bgp.BgpExc as ex:
|
||||
conn_lost_reason = 'Connection to peer lost, reason: %s.' % ex
|
||||
except Exception as e:
|
||||
LOG.debug(traceback.format_exc())
|
||||
@ -570,7 +559,7 @@ class BgpProtocol(Protocol, Activity):
|
||||
assert self.state == BGP_FSM_CONNECT
|
||||
# We have a connection with peer we send open message.
|
||||
open_msg = self._peer.create_open_msg()
|
||||
self._holdtime = open_msg.holdtime
|
||||
self._holdtime = open_msg.hold_time
|
||||
self.state = BGP_FSM_OPEN_SENT
|
||||
if not self.is_reactive:
|
||||
self._peer.state.bgp_state = self.state
|
||||
|
||||
@ -19,14 +19,16 @@
|
||||
import logging
|
||||
import socket
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.messages import Update
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv4_VPN
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_IPv6_VPN
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_RTC_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RtNlri
|
||||
from ryu.services.protocols.bgp.protocols.bgp import pathattr
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import Med
|
||||
from ryu.lib.packet.bgp import BGPUpdate
|
||||
from ryu.lib.packet.bgp import RF_IPv4_UC
|
||||
from ryu.lib.packet.bgp import RF_IPv4_VPN
|
||||
from ryu.lib.packet.bgp import RF_IPv6_VPN
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
from ryu.lib.packet.bgp import RouteTargetMembershipNLRI
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MULTI_EXIT_DISC
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeMultiExitDisc
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeMpUnreachNLRI
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeUnknown
|
||||
from ryu.services.protocols.bgp.info_base.rtc import RtcPath
|
||||
from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Path
|
||||
from ryu.services.protocols.bgp.info_base.vpnv4 import Vpnv4Path
|
||||
@ -43,7 +45,7 @@ _ROUTE_FAMILY_TO_PATH_MAP = {RF_IPv4_UC: Ipv4Path,
|
||||
|
||||
|
||||
def create_path(src_peer, nlri, **kwargs):
|
||||
route_family = nlri.route_family
|
||||
route_family = nlri.ROUTE_FAMILY
|
||||
assert route_family in _ROUTE_FAMILY_TO_PATH_MAP.keys()
|
||||
path_cls = _ROUTE_FAMILY_TO_PATH_MAP.get(route_family)
|
||||
return path_cls(src_peer, nlri, src_peer.version_num, **kwargs)
|
||||
@ -57,7 +59,7 @@ def clone_path_and_update_med_for_target_neighbor(path, med):
|
||||
route_family)
|
||||
path_cls = _ROUTE_FAMILY_TO_PATH_MAP.get(route_family)
|
||||
pattrs = path.pathattr_map
|
||||
pattrs[Med.ATTR_NAME] = Med(med)
|
||||
pattrs[BGP_ATTR_TYPE_MULTI_EXIT_DISC] = BGPPathAttributeMultiExitDisc(med)
|
||||
return path_cls(
|
||||
path.source, path.nlri, path.source_version_num,
|
||||
pattrs=pattrs, nexthop=path.nexthop,
|
||||
@ -77,7 +79,7 @@ def clone_rtcpath_update_rt_as(path, new_rt_as):
|
||||
if not path or path.route_family != RF_RTC_UC:
|
||||
raise ValueError('Expected RT_NLRI path')
|
||||
old_nlri = path.nlri
|
||||
new_rt_nlri = RtNlri(new_rt_as, old_nlri.route_target)
|
||||
new_rt_nlri = RouteTargetMembershipNLRI(new_rt_as, old_nlri.route_target)
|
||||
return RtcPath(path.source, new_rt_nlri, path.source_version_num,
|
||||
pattrs=path.pathattr_map, nexthop=path.nexthop,
|
||||
is_withdraw=path.is_withdraw)
|
||||
@ -106,7 +108,7 @@ def get_unknow_opttrans_attr(path):
|
||||
path_attrs = path.pathattr_map
|
||||
unknown_opt_tran_attrs = {}
|
||||
for _, attr in path_attrs.iteritems():
|
||||
if (isinstance(attr, pathattr.UnRcgPathAttr) and
|
||||
if (isinstance(attr, BGPPathAttributeUnknown) and
|
||||
attr.is_optional_transitive()):
|
||||
unknown_opt_tran_attrs[attr.type_code] = attr
|
||||
return unknown_opt_tran_attrs
|
||||
@ -114,9 +116,10 @@ def get_unknow_opttrans_attr(path):
|
||||
|
||||
def create_end_of_rib_update():
|
||||
"""Construct end-of-rib (EOR) Update instance."""
|
||||
mpunreach_attr = pathattr.MpUnreachNlri(RF_IPv4_VPN, [])
|
||||
pathattr_map = {pathattr.MpUnreachNlri.ATTR_NAME: mpunreach_attr}
|
||||
eor = Update(pathattr_map)
|
||||
mpunreach_attr = BGPPathAttributeMpUnreachNLRI(RF_IPv4_VPN.afi,
|
||||
RF_IPv4_VPN.safi,
|
||||
[])
|
||||
eor = BGPUpdate(path_attributes=[mpunreach_attr])
|
||||
return eor
|
||||
|
||||
|
||||
|
||||
@ -18,10 +18,12 @@
|
||||
"""
|
||||
import logging
|
||||
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RF_RTC_UC
|
||||
from ryu.services.protocols.bgp.protocols.bgp.nlri import RtNlri
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import AsPath
|
||||
from ryu.services.protocols.bgp.protocols.bgp.pathattr import Origin
|
||||
from ryu.lib.packet.bgp import RF_RTC_UC
|
||||
from ryu.lib.packet.bgp import RouteTargetMembershipNLRI
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH
|
||||
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeAsPath
|
||||
from ryu.lib.packet.bgp import BGPPathAttributeOrigin
|
||||
from ryu.services.protocols.bgp.base import OrderedDict
|
||||
from ryu.services.protocols.bgp.info_base.rtc import RtcPath
|
||||
|
||||
@ -75,14 +77,15 @@ class RouteTargetManager(object):
|
||||
|
||||
def _add_rt_nlri_for_as(self, rtc_as, route_target, is_withdraw=False):
|
||||
from ryu.services.protocols.bgp.core import EXPECTED_ORIGIN
|
||||
rt_nlri = RtNlri(rtc_as, route_target)
|
||||
rt_nlri = RouteTargetMembershipNLRI(rtc_as, route_target)
|
||||
# Create a dictionary for path-attrs.
|
||||
pattrs = OrderedDict()
|
||||
if not is_withdraw:
|
||||
# MpReachNlri and/or MpUnReachNlri attribute info. is contained
|
||||
# in the path. Hence we do not add these attributes here.
|
||||
pattrs[Origin.ATTR_NAME] = Origin(EXPECTED_ORIGIN)
|
||||
pattrs[AsPath.ATTR_NAME] = AsPath([])
|
||||
pattrs[BGP_ATTR_TYPE_ORIGIN] = BGPPathAttributeOrigin(
|
||||
EXPECTED_ORIGIN)
|
||||
pattrs[BGP_ATTR_TYPE_AS_PATH] = BGPPathAttributeAsPath([])
|
||||
|
||||
# Create Path instance and initialize appropriately.
|
||||
path = RtcPath(None, rt_nlri, 0, is_withdraw=is_withdraw,
|
||||
@ -152,7 +155,7 @@ class RouteTargetManager(object):
|
||||
else:
|
||||
# New RT could be Default RT, which means we need to share this
|
||||
# path
|
||||
desired_rts.add(RtNlri.DEFAULT_RT)
|
||||
desired_rts.add(RouteTargetMembershipNLRI.DEFAULT_RT)
|
||||
# If we have RT filter has new RTs that are common with path
|
||||
# RTs, then we send this path to peer
|
||||
if desired_rts.intersection(new_rts):
|
||||
@ -172,8 +175,8 @@ class RouteTargetManager(object):
|
||||
interested_rts.update(self._vrfs_conf.vrf_interested_rts)
|
||||
# Remove default RT as it is not a valid RT for paths
|
||||
# TODO(PH): Check if we have better alternative than add and remove
|
||||
interested_rts.add(RtNlri.DEFAULT_RT)
|
||||
interested_rts.remove(RtNlri.DEFAULT_RT)
|
||||
interested_rts.add(RouteTargetMembershipNLRI.DEFAULT_RT)
|
||||
interested_rts.remove(RouteTargetMembershipNLRI.DEFAULT_RT)
|
||||
return interested_rts
|
||||
|
||||
def update_interested_rts(self):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user