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:
&#149; 3 signs your SCM is hindering your productivity
&#149; Requirements for releasing software faster
&#149; 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

Reply via email to