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:
ISHIDA Wataru 2014-04-16 04:13:39 +00:00 committed by FUJITA Tomonori
parent bdad6267de
commit 9d5e66fa4e
26 changed files with 567 additions and 478 deletions

View File

@ -79,9 +79,9 @@ def reset_neighor(ip_address):
return True
#==============================================================================
# =============================================================================
# Common configuration related APIs
#==============================================================================
# =============================================================================
@register(name='comm_conf.get')
def get_common_conf():

View File

@ -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')

View File

@ -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
])

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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))

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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):