to try mp-bgp feature, use mpbgp_sample_conf.py for the configuration file.
you can add vpn prefix like this bgpd> prefix add_local 100:100 192.168.0.0/24 10.0.0.1 and delete prefix by bgpd> prefix delete_local 100:100 192.168.0.0/24 Signed-off-by: ISHIDA Wataru <[email protected]> --- ryu/lib/packet/bgp.py | 101 +++++++++++++----- ryu/services/protocols/bgp/application.py | 5 +- .../protocols/bgp/core_managers/peer_manager.py | 1 + .../protocols/bgp/core_managers/table_manager.py | 16 ++- ryu/services/protocols/bgp/info_base/base.py | 2 +- ryu/services/protocols/bgp/info_base/rtc.py | 5 +- ryu/services/protocols/bgp/info_base/vpn.py | 2 +- ryu/services/protocols/bgp/info_base/vrf.py | 30 ++++-- ryu/services/protocols/bgp/mpbgp_sample_conf.py | 112 ++++++++++++++++++++ .../protocols/bgp/operator/commands/prefix.py | 59 +++++++++++ .../protocols/bgp/operator/commands/root.py | 4 +- ryu/services/protocols/bgp/peer.py | 4 +- ryu/services/protocols/bgp/rtconf/vrfs.py | 2 +- 13 files changed, 292 insertions(+), 51 deletions(-) create mode 100644 ryu/services/protocols/bgp/mpbgp_sample_conf.py create mode 100644 ryu/services/protocols/bgp/operator/commands/prefix.py diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index 6882770..4f24b0e 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -26,6 +26,9 @@ import abc import six import struct import copy +import logging + +LOG = logging.getLogger('ryu.lib.packet.bgp') from ryu.ofproto.ofproto_parser import msg_pack_into from ryu.lib.stringify import StringifyMixin @@ -505,6 +508,13 @@ RF_IPv4_VPN = RouteFamily(afi.IP, safi.MPLS_VPN) RF_IPv6_VPN = RouteFamily(afi.IP6, safi.MPLS_VPN) RF_RTC_UC = RouteFamily(afi.IP, safi.ROUTE_TARGET_CONSTRTAINS) +_rf_map = { + (afi.IP, safi.UNICAST) : RF_IPv4_UC, + (afi.IP6, safi.UNICAST) : RF_IPv6_UC, + (afi.IP, safi.MPLS_VPN) : RF_IPv4_VPN, + (afi.IP6, safi.MPLS_VPN) : RF_IPv6_VPN, + (afi.IP, safi.ROUTE_TARGET_CONSTRTAINS) : RF_RTC_UC + } def pad(bin, len_): assert len(bin) <= len_ @@ -699,8 +709,11 @@ class _VPNAddrPrefix(_AddrPrefix): def _prefix_to_bin(cls, addr): rd = addr[0] rest = addr[1:] - binrd = bytearray() - msg_pack_into(cls._RD_PACK_STR, binrd, 0, rd) + asnum, localadmin = rd.split(':') + rd = BGPTwoOctetAsSpecificExtendedCommunity(subtype=2, + as_number=int(asnum), + local_administrator=int(localadmin)) + binrd = rd.serialize() return binrd + super(_VPNAddrPrefix, cls)._prefix_to_bin(rest) @classmethod @@ -714,6 +727,11 @@ class _VPNAddrPrefix(_AddrPrefix): class IPAddrPrefix(_UnlabelledAddrPrefix, _IPAddrPrefix): ROUTE_FAMILY = RF_IPv4_UC + def __init__(self, prefix): + addr, masklen = prefix.split('/') + super(IPAddrPrefix, self).__init__(length=int(masklen), + addr=addr) + @property def prefix(self): return self.addr+'/{0}'.format(self.length) @@ -726,6 +744,11 @@ class IPAddrPrefix(_UnlabelledAddrPrefix, _IPAddrPrefix): class IP6AddrPrefix(_UnlabelledAddrPrefix, _IP6AddrPrefix): ROUTE_FAMILY = RF_IPv6_UC + def __init__(self, prefix): + addr, masklen = prefix.split('/') + super(IP6AddrPrefix, self).__init__(length=int(masklen), + addr=addr) + @property def prefix(self): return self.addr+'/{0}'.format(self.length) @@ -739,9 +762,23 @@ class LabelledVPNIPAddrPrefix(_LabelledAddrPrefix, _VPNAddrPrefix, _IPAddrPrefix): ROUTE_FAMILY = RF_IPv4_VPN + def __init__(self, prefix='0.0.0.0/32', route_dist=0, labels=[], + length=None, addr=None): + if length and addr: + super(LabelledVPNIPAddrPrefix, self).__init__(length=length, + addr=addr) + else: + addr, masklen = prefix.split('/') + super(LabelledVPNIPAddrPrefix, self).__init__(length=int(masklen), + addr=addr, + labels=labels, + route_dist=route_dist) + @property def prefix(self): - return self.addr[-1]+'/{0}'.format(self.length) + masklen = self.length - struct.calcsize(self._RD_PACK_STR) * 8 \ + - struct.calcsize(self._LABEL_PACK_STR) * 8 * len(self.addr[:-2]) + return self.addr[-1]+'/{0}'.format(masklen) @property def route_disc(self): @@ -760,9 +797,18 @@ class LabelledVPNIP6AddrPrefix(_LabelledAddrPrefix, _VPNAddrPrefix, _IP6AddrPrefix): ROUTE_FAMILY = RF_IPv6_VPN + def __init__(self, prefix, route_dist=0, labels=[]): + addr, masklen = prefix.split('/') + super(LabelledVPNIP6AddrPrefix, self).__init__(length=int(masklen), + addr=addr, + labels=labels, + route_dist=route_dist) + @property def prefix(self): - return self.addr[-1]+'/{0}'.format(self.length) + masklen = self.length - struct.calcsize(self._RD_PACK_STR) * 8 \ + - struct.calcsize(self._LABEL_PACK_STR) * 8 * len(self.addr[:-2]) + return self.addr[-1]+'/{0}'.format(masklen) @property def route_disc(self): @@ -862,26 +908,7 @@ class RouteTargetMembershipNLRI(StringifyMixin): # Extract route target. route_target = '' - etype, esubtype, payload = struct.unpack_from('BB6s', buf, idx) - # RFC says: The value of the high-order octet of the Type field for the - # Route Target Community can be 0x00, 0x01, or 0x02. The value of the - # low-order octet of the Type field for this community is 0x02. - # TODO(PH): Remove this exception when it breaks something Here we make - # exception as Routem packs lower-order octet as 0x00 - if etype in (0, 2) and esubtype in (0, 2): - # If we have route target community in AS number format. - asnum, i = struct.unpack('!HI', payload) - route_target = ('%s:%s' % (asnum, i)) - elif etype == 1 and esubtype == 2: - # If we have route target community in IP address format. - ip_addr, i = struct.unpack('!4sH', payload) - ip_addr = socket.inet_ntoa(ip_addr) - route_target = ('%s:%s' % (ip_addr, i)) - elif etype == 0 and esubtype == 1: - # TODO(PH): Parsing of RtNlri 1:1:100:1 - asnum, i = struct.unpack('!HI', payload) - route_target = ('%s:%s' % (asnum, i)) - + route_target = _ExtendedCommunity(buf[idx:]) return cls(origin_as, route_target) def serialize(self): @@ -1549,6 +1576,25 @@ class BGPPathAttributeExtendedCommunities(_PathAttribute): buf += comm.serialize() return buf + def _community_list(self, subtype): + _list = [] + for comm in (c for c in self.communities if c.subtype == subtype): + if comm.type == 0 or comm.type == 2: + _list.append('%d:%d' % (comm.as_number, + comm.local_administrator)) + elif comm.type == 1: + _list.append('%s:%d' % (comm.ipv4_address, + comm.local_administrator)) + return _list + + @property + def rt_list(self): + return self._community_list(2) + + @property + def soo_list(self): + return self._community_list(3) + class _ExtendedCommunity(StringifyMixin, _TypeDisp, _Value): _PACK_STR = '!B7s' # type high (+ type low) + value @@ -1716,6 +1762,9 @@ class BGPPathAttributeMpReachNLRI(_PathAttribute): buf += binnlri return buf + @property + def route_family(self): + return _rf_map[(self.afi, self.safi)] @_PathAttribute.register_type(BGP_ATTR_TYPE_MP_UNREACH_NLRI) class BGPPathAttributeMpUnreachNLRI(_PathAttribute): @@ -1759,6 +1808,10 @@ class BGPPathAttributeMpUnreachNLRI(_PathAttribute): buf += binnlri return buf + @property + def route_family(self): + return _rf_map[(self.afi, self.safi)] + class BGPNLRI(IPAddrPrefix): pass diff --git a/ryu/services/protocols/bgp/application.py b/ryu/services/protocols/bgp/application.py index 6737d7d..ab58798 100644 --- a/ryu/services/protocols/bgp/application.py +++ b/ryu/services/protocols/bgp/application.py @@ -44,6 +44,7 @@ from ryu.services.protocols.bgp.rtconf.common import REFRESH_MAX_EOR_TIME from ryu.services.protocols.bgp.rtconf.common import REFRESH_STALEPATH_TIME from ryu.services.protocols.bgp.rtconf.common import ROUTER_ID from ryu.services.protocols.bgp.rtconf import neighbors +from ryu.services.protocols.bgp.rtconf import vrfs from ryu.services.protocols.bgp.utils.dictconfig import dictConfig from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4 @@ -206,10 +207,10 @@ class BGPSpeaker(RyuApp): All valid VRFs are loaded. """ vpns_conf = routing_settings.setdefault('vpns', {}) - for vrf in vpns_conf: + for vrfname, vrf in vpns_conf.iteritems(): try: + vrf[vrfs.VRF_NAME] = vrfname call('vrf.create', **vrf) - LOG.debug('Added vrf %s' % str(vrf)) except RuntimeConfigError as e: LOG.error(e) continue diff --git a/ryu/services/protocols/bgp/core_managers/peer_manager.py b/ryu/services/protocols/bgp/core_managers/peer_manager.py index 505ffc8..8fba6b0 100644 --- a/ryu/services/protocols/bgp/core_managers/peer_manager.py +++ b/ryu/services/protocols/bgp/core_managers/peer_manager.py @@ -10,6 +10,7 @@ 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 RouteTargetMembershipNLRI from ryu.services.protocols.bgp.utils.bgp \ import clone_path_and_update_med_for_target_neighbor LOG = logging.getLogger('bgpspeaker.core_managers.peer_manager') diff --git a/ryu/services/protocols/bgp/core_managers/table_manager.py b/ryu/services/protocols/bgp/core_managers/table_manager.py index a701644..b9f1f9c 100644 --- a/ryu/services/protocols/bgp/core_managers/table_manager.py +++ b/ryu/services/protocols/bgp/core_managers/table_manager.py @@ -467,8 +467,7 @@ 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.') - ip, masklen = prefix.split('/') - prefix = IPAddrPrefix(int(masklen), ip) + prefix = IPAddrPrefix(prefix) elif route_family == VRF_RF_IPV6: vrf_table = self._tables.get(table_id) if vrf_table is None: @@ -476,16 +475,14 @@ 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.') - ip6, masklen = prefix.split('/') - prefix = IP6AddrPrefix(int(masklen), ip6) + prefix = IP6AddrPrefix(prefix) return vrf_table.insert_vrf_path( - prefix, next_hop=next_hop, + prefix, next_hop=BGPPathAttributeNextHop(next_hop), gen_lbl=True ) def add_to_ipv4_global_table(self, prefix): - ip, masklen = prefix.split('/') - _nlri = IPAddrPrefix(int(masklen), ip) + nlri = IPAddrPrefix(prefix) src_ver_num = 1 peer = None # set mandatory path attributes @@ -497,7 +494,7 @@ class TableCoreManager(object): pathattrs[BGP_ATTR_TYPE_ORIGIN] = origin pathattrs[BGP_ATTR_TYPE_AS_PATH] = aspath - new_path = Ipv4Path(peer, _nlri, src_ver_num, + new_path = Ipv4Path(peer, nlri, src_ver_num, pattrs=pathattrs, nexthop=nexthop) # add to global ipv4 table and propagates to neighbors self.learn_path(new_path) @@ -526,8 +523,7 @@ class TableCoreManager(object): if not vrf_table: raise BgpCoreError(desc='Vrf for route distinguisher %s does ' 'not exist.' % route_dist) - ip, masklen = prefix.split('/') - prefix = IPAddrPrefix(int(masklen), ip) + prefix = IPAddrPrefix(prefix) else: vrf_table = self._tables.get(table_id) if not vrf_table: diff --git a/ryu/services/protocols/bgp/info_base/base.py b/ryu/services/protocols/bgp/info_base/base.py index c735c30..9d177c5 100644 --- a/ryu/services/protocols/bgp/info_base/base.py +++ b/ryu/services/protocols/bgp/info_base/base.py @@ -765,7 +765,7 @@ class Path(object): if extcomm_attr is None: rts = [] else: - rts = extcomm_attr.rt_list[:] + rts = extcomm_attr.rt_list return rts def has_rts_in(self, interested_rts): diff --git a/ryu/services/protocols/bgp/info_base/rtc.py b/ryu/services/protocols/bgp/info_base/rtc.py index 6f6e332..69a40ad 100644 --- a/ryu/services/protocols/bgp/info_base/rtc.py +++ b/ryu/services/protocols/bgp/info_base/rtc.py @@ -20,6 +20,7 @@ import logging from ryu.lib.packet.bgp import RF_RTC_UC +from ryu.lib.packet.bgp import BGPPathAttributeNextHop from ryu.services.protocols.bgp.info_base.base import Destination from ryu.services.protocols.bgp.info_base.base import NonVrfPathProcessingMixin @@ -67,7 +68,7 @@ class RtcPath(Path): ROUTE_FAMILY = RF_RTC_UC def __init__(self, source, nlri, src_ver_num, pattrs=None, - nexthop='0.0.0.0', is_withdraw=False, - med_set_by_target_neighbor=False): + nexthop=BGPPathAttributeNextHop('0.0.0.0'), + is_withdraw=False, med_set_by_target_neighbor=False): Path.__init__(self, source, nlri, src_ver_num, pattrs, nexthop, is_withdraw, med_set_by_target_neighbor) diff --git a/ryu/services/protocols/bgp/info_base/vpn.py b/ryu/services/protocols/bgp/info_base/vpn.py index 3b0c81f..2bb5704 100644 --- a/ryu/services/protocols/bgp/info_base/vpn.py +++ b/ryu/services/protocols/bgp/info_base/vpn.py @@ -44,7 +44,7 @@ class VpnTable(Table): """Return a key that will uniquely identify this vpnvX NLRI inside this table. """ - return vpn_nlri.route_disc + ':' + vpn_nlri.prefix + return str(vpn_nlri.route_disc) + ':' + vpn_nlri.prefix def _create_dest(self, nlri): return self.VPN_DEST_CLASS(self, nlri) diff --git a/ryu/services/protocols/bgp/info_base/vrf.py b/ryu/services/protocols/bgp/info_base/vrf.py index 30b53a2..4f58fe1 100644 --- a/ryu/services/protocols/bgp/info_base/vrf.py +++ b/ryu/services/protocols/bgp/info_base/vrf.py @@ -27,6 +27,7 @@ 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 BGPTwoOctetAsSpecificExtendedCommunity from ryu.lib.packet.bgp import BGPPathAttributeMultiExitDisc from ryu.services.protocols.bgp.base import OrderedDict @@ -212,9 +213,24 @@ class VrfTable(Table): pattrs[BGP_ATTR_TYPE_ORIGIN] = BGPPathAttributeOrigin( EXPECTED_ORIGIN) pattrs[BGP_ATTR_TYPE_AS_PATH] = BGPPathAttributeAsPath([]) + communities = [] + for rt in vrf_conf.export_rts: + as_num, local_admin = rt.split(':') + subtype = 2 + communities.append(BGPTwoOctetAsSpecificExtendedCommunity( + as_number=int(as_num), + local_administrator=int(local_admin), + subtype=subtype)) + for soo in vrf_conf.soo_list: + as_num, local_admin = rt.split(':') + subtype = 3 + communities.append(BGPTwoOctetAsSpecificExtendedCommunity( + as_number=int(as_num), + local_administrator=int(local_admin), + subtype=subtype)) + pattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = \ - BGPPathAttributeExtendedCommunities( - rt_list=vrf_conf.export_rts, soo_list=vrf_conf.soo_list) + BGPPathAttributeExtendedCommunities(communities=communities) if vrf_conf.multi_exit_disc: pattrs[BGP_ATTR_TYPE_MULTI_EXIT_DISC] = \ BGPPathAttributeMultiExitDisc(vrf_conf.multi_exit_disc) @@ -452,7 +468,7 @@ class VrfPath(Path): @staticmethod def create_puid(route_disc, ip_prefix): assert route_disc and ip_prefix - return route_disc + ':' + ip_prefix + return str(route_disc) + ':' + ip_prefix def clone(self, for_withdrawal=False): pathattrs = None @@ -471,10 +487,10 @@ class VrfPath(Path): ) return clone - def clone_to_vpn(self, route_disc, for_withdrawal=False): - vpn_nlri = self.VPN_NLRI_CLASS( - self.label_list, route_disc, self._nlri.prefix - ) + def clone_to_vpn(self, route_dist, for_withdrawal=False): + vpn_nlri = self.VPN_NLRI_CLASS(prefix=self._nlri.prefix, + labels=self.label_list, + route_dist=route_dist) pathattrs = None if not for_withdrawal: diff --git a/ryu/services/protocols/bgp/mpbgp_sample_conf.py b/ryu/services/protocols/bgp/mpbgp_sample_conf.py new file mode 100644 index 0000000..1611f7b --- /dev/null +++ b/ryu/services/protocols/bgp/mpbgp_sample_conf.py @@ -0,0 +1,112 @@ +import os + +# ============================================================================= +# BGP configuration. +# ============================================================================= +BGP = { + + # General BGP configuration. + 'routing': { + # ASN for this BGP instance. + 'local_as': 64512, + + # BGP Router ID. + 'router_id': '10.10.0.1', + + # We list all BGP neighbors below. We establish EBGP sessions with peer + # with different AS number then configured above. We will + # establish IBGP session if AS number is same. + 'bgp_neighbors': { + '10.10.0.2': { + 'cap_mbgp_ipv4': False, + 'cap_mbgp_vpnv4': True, + 'remote_as': 64513, + }, + }, + + 'vpns' : { + 'vpnA' : { + 'route_dist' : '100:100', + 'import_rts' : ['100:100'], + 'export_rts' : ['100:100'] + } + } + }, + +} + +# ============================================================================= +# Logging configuration. +# ============================================================================= +LOGGING = { + + # We use python logging package for logging. + 'version': 1, + 'disable_existing_loggers': False, + + 'formatters': { + 'verbose': { + 'format': '%(levelname)s %(asctime)s %(module)s ' + + '[%(process)d %(thread)d] %(message)s' + }, + 'simple': { + 'format': '%(levelname)s %(asctime)s %(module)s %(lineno)s ' + + '%(message)s' + }, + 'stats': { + 'format': '%(message)s' + }, + }, + + 'handlers': { + # Outputs log to console. + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'formatter': 'simple' + }, + 'console_stats': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'formatter': 'stats' + }, + # Rotates log file when its size reaches 10MB. + 'log_file': { + 'level': 'ERROR', + 'class': 'logging.handlers.RotatingFileHandler', + 'filename': os.path.join('.', 'bgpspeaker.log'), + 'maxBytes': '10000000', + 'formatter': 'verbose' + }, + 'stats_file': { + 'level': 'DEBUG', + 'class': 'logging.handlers.RotatingFileHandler', + 'filename': os.path.join('.', 'statistics_bgps.log'), + 'maxBytes': '10000000', + 'formatter': 'stats' + }, + }, + + # Fine-grained control of logging per instance. + 'loggers': { + 'bgpspeaker': { + 'handlers': ['console', 'log_file'], + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'stats': { + 'handlers': ['stats_file', 'console_stats'], + 'level': 'INFO', + 'propagate': False, + 'formatter': 'stats', + }, + }, + + # Root loggers. + 'root': { + 'handlers': ['console', 'log_file'], + 'level': 'DEBUG', + 'propagate': True, + }, +} diff --git a/ryu/services/protocols/bgp/operator/commands/prefix.py b/ryu/services/protocols/bgp/operator/commands/prefix.py new file mode 100644 index 0000000..c5ed0e2 --- /dev/null +++ b/ryu/services/protocols/bgp/operator/commands/prefix.py @@ -0,0 +1,59 @@ +import logging + +from ryu.services.protocols.bgp.api.base import call +from ryu.services.protocols.bgp.core import BgpCoreError +from ryu.services.protocols.bgp.operator.command import Command +from ryu.services.protocols.bgp.operator.command import CommandsResponse +from ryu.services.protocols.bgp.operator.command import STATUS_OK +from ryu.services.protocols.bgp.operator.command import STATUS_ERROR +from ryu.services.protocols.bgp.operator.commands.responses import \ + WrongParamResp + +LOG = logging.getLogger('bgpspeaker.operator.commands.prefix') + +class DeleteLocalCmd(Command): + help_msg = 'delete local prefix to specific vrf' + param_help_msg = '<route_dist> <prefix>' + command = 'delete_local' + + def action(self, params): + if len(params) != 2: + return WrongParamResp() + try: + rd = params[0] + prefix = params[1] + call('prefix.delete_local', route_dist=rd, prefix=prefix) + return CommandsResponse(STATUS_OK, None) + except BgpCoreError as e: + return CommandsResponse(STATUS_ERROR, e) + + +class AddLocalCmd(Command): + help_msg = 'add local prefix to specific vrf' + param_help_msg = '<route_dist> <prefix> <nexthop>' + command = 'add_local' + + def action(self, params): + if len(params) != 3: + return WrongParamResp() + try: + rd = params[0] + prefix = params[1] + nexthop = params[2] + call('prefix.add_local', **{'route_dist' : rd, + 'prefix' : prefix, + 'next_hop' : nexthop}) + return CommandsResponse(STATUS_OK, None) + except BgpCoreError as e: + return CommandsResponse(STATUS_ERROR, e) + + +class PrefixCmd(Command): + help_msg = 'add/delete local prefix' + command = 'prefix' + + subcommands = {'add_local': AddLocalCmd, + 'delete_local' : DeleteLocalCmd} + + def action(self, params): + return CommandsResponse(STATUS_ERROR, 'Command incomplete') diff --git a/ryu/services/protocols/bgp/operator/commands/root.py b/ryu/services/protocols/bgp/operator/commands/root.py index cf6d5cd..6e7a8ce 100644 --- a/ryu/services/protocols/bgp/operator/commands/root.py +++ b/ryu/services/protocols/bgp/operator/commands/root.py @@ -2,10 +2,12 @@ from ryu.services.protocols.bgp.operator.command import Command from ryu.services.protocols.bgp.operator.commands.clear import ClearCmd from ryu.services.protocols.bgp.operator.commands.set import SetCmd from ryu.services.protocols.bgp.operator.commands.show import ShowCmd +from ryu.services.protocols.bgp.operator.commands.prefix import PrefixCmd class RootCmd(Command): subcommands = { 'show': ShowCmd, 'set': SetCmd, - 'clear': ClearCmd} + 'clear': ClearCmd, + 'prefix': PrefixCmd} diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py index 0779206..2ed1b90 100644 --- a/ryu/services/protocols/bgp/peer.py +++ b/ryu/services/protocols/bgp/peer.py @@ -1142,7 +1142,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity): self, msg_nlri, pattrs=umsg_pattrs, - nexthop=next_hop + nexthop=BGPPathAttributeNextHop(next_hop) ) LOG.debug('Extracted paths from Update msg.: %s' % new_path) # Update appropriate table with new paths. @@ -1271,7 +1271,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity): self, msg_nlri, pattrs=umsg_pattrs, - nexthop=next_hop + nexthop=BGPPathAttributeNextHop(next_hop) ) LOG.debug('Extracted paths from Update msg.: %s' % new_path) if msg_rf == RF_RTC_UC \ diff --git a/ryu/services/protocols/bgp/rtconf/vrfs.py b/ryu/services/protocols/bgp/rtconf/vrfs.py index 48b4809..51c7a16 100644 --- a/ryu/services/protocols/bgp/rtconf/vrfs.py +++ b/ryu/services/protocols/bgp/rtconf/vrfs.py @@ -134,7 +134,7 @@ class VrfConf(ConfWithId, ConfWithStats): EXPORT_RTS]) OPTIONAL_SETTINGS = frozenset( - [MULTI_EXIT_DISC, SITE_OF_ORIGINS, VRF_RF, IMPORT_MAPS] + [VRF_NAME, MULTI_EXIT_DISC, SITE_OF_ORIGINS, VRF_RF, IMPORT_MAPS] ) def __init__(self, **kwargs): -- 1.7.9.5 ------------------------------------------------------------------------------ Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce _______________________________________________ Ryu-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ryu-devel
