def insert_vrffs_path(self, nlri, communities, is_withdraw=False):
        assert nlri
        assert isinstance(communities, list)
        vrf_conf = self.vrf_conf

        from ryu.services.protocols.bgp.core import EXPECTED_ORIGIN
        pattrs = OrderedDict()
        pattrs[BGP_ATTR_TYPE_ORIGIN] = BGPPathAttributeOrigin(EXPECTED_ORIGIN)
        pattrs[BGP_ATTR_TYPE_AS_PATH] = BGPPathAttributeAsPath([])

        for rt in vrf_conf.export_rts:
            communities.append(create_rt_extended_community(rt, 2))
        for soo in vrf_conf.soo_list:
            communities.append(create_rt_extended_community(soo, 3))

        pattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = (
            BGPPathAttributeExtendedCommunities(communities=communities))

        puid = self.VRF_PATH_CLASS.create_puid(vrf_conf.route_dist,
                                               nlri.prefix)

        path = self.VRF_PATH_CLASS(puid,
                                   None,
                                   nlri,
                                   0,
                                   pattrs=pattrs,
                                   is_withdraw=is_withdraw)

        # Insert the path into VRF table, get affected destination so that we
        # can process it further.
        eff_dest = self.insert(path)
        # Enqueue the eff_dest for further processing.
        self._signal_bus.dest_changed(eff_dest)
Beispiel #2
0
    def insert_vrf_path(self,
                        ip_nlri,
                        next_hop=None,
                        gen_lbl=False,
                        is_withdraw=False):
        assert ip_nlri
        pattrs = None
        label_list = []
        vrf_conf = self.vrf_conf
        if not is_withdraw:
            # Create a dictionary for path-attrs.
            pattrs = OrderedDict()

            # MpReachNlri and/or MpUnReachNlri attribute info. is contained
            # in the path. Hence we do not add these attributes here.
            from ryu.services.protocols.bgp.core import EXPECTED_ORIGIN

            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[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:
                # Label per next_hop demands we use a different label
                # per next_hop. Here connected interfaces are advertised per
                # VRF.
                label_key = (vrf_conf.route_dist, next_hop)
                nh_label = table_manager.get_nexthop_label(label_key)
                if not nh_label:
                    nh_label = table_manager.get_next_vpnv4_label()
                    table_manager.set_nexthop_label(label_key, nh_label)
                label_list.append(nh_label)

            elif gen_lbl:
                # If we do not have next_hop, get a new label.
                label_list.append(table_manager.get_next_vpnv4_label())

        puid = self.VRF_PATH_CLASS.create_puid(vrf_conf.route_dist,
                                               ip_nlri.prefix)
        path = self.VRF_PATH_CLASS(puid,
                                   None,
                                   ip_nlri,
                                   0,
                                   pattrs=pattrs,
                                   nexthop=next_hop,
                                   label_list=label_list,
                                   is_withdraw=is_withdraw)

        # Insert the path into VRF table, get affected destination so that we
        # can process it further.
        eff_dest = self.insert(path)
        # Enqueue the eff_dest for further processing.
        self._signal_bus.dest_changed(eff_dest)
        return label_list
Beispiel #3
0
    def get_configured_capabilites(self):
        """Returns configured capabilities."""

        capabilities = OrderedDict()
        mbgp_caps = []
        if self.cap_mbgp_ipv4:
            mbgp_caps.append(MultiprotocolExtentionCap(RF_IPv4_UC))

        if self.cap_mbgp_vpnv4:
            mbgp_caps.append(MultiprotocolExtentionCap(RF_IPv4_VPN))

        if self.cap_mbgp_vpnv6:
            mbgp_caps.append(MultiprotocolExtentionCap(RF_IPv6_VPN))

        if self.cap_rtc:
            mbgp_caps.append(MultiprotocolExtentionCap(RF_RTC_UC))

        if mbgp_caps:
            capabilities[MultiprotocolExtentionCap.CODE] = mbgp_caps

        if self.cap_refresh:
            capabilities[RouteRefreshCap.CODE] = [
                RouteRefreshCap.get_singleton()
            ]

        if self.cap_enhanced_refresh:
            capabilities[EnhancedRouteRefreshCap.CODE] = [
                EnhancedRouteRefreshCap.get_singleton()
            ]

        return capabilities
Beispiel #4
0
    def get_configured_capabilities(self):
        """Returns configured capabilities."""

        capabilities = OrderedDict()
        mbgp_caps = []
        if self.cap_mbgp_ipv4:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(
                    RF_IPv4_UC.afi, RF_IPv4_UC.safi))

        if self.cap_mbgp_ipv6:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(
                    RF_IPv6_UC.afi, RF_IPv6_UC.safi))

        if self.cap_mbgp_vpnv4:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(
                    RF_IPv4_VPN.afi, RF_IPv4_VPN.safi))

        if self.cap_mbgp_vpnv6:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(
                    RF_IPv6_VPN.afi, RF_IPv6_VPN.safi))

        if self.cap_rtc:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(
                    RF_RTC_UC.afi, RF_RTC_UC.safi))

        if self.cap_mbgp_evpn:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(
                    RF_L2_EVPN.afi, RF_L2_EVPN.safi))

        if mbgp_caps:
            capabilities[BGP_CAP_MULTIPROTOCOL] = mbgp_caps

        if self.cap_refresh:
            capabilities[BGP_CAP_ROUTE_REFRESH] = [
                BGPOptParamCapabilityRouteRefresh()]

        if self.cap_enhanced_refresh:
            capabilities[BGP_CAP_ENHANCED_ROUTE_REFRESH] = [
                BGPOptParamCapabilityEnhancedRouteRefresh()]

        if self.cap_four_octet_as_number:
            capabilities[BGP_CAP_FOUR_OCTET_AS_NUMBER] = [
                BGPOptParamCapabilityFourOctetAsNumber(self.local_as)]

        return capabilities
Beispiel #5
0
    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)
        # 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([])

        # Create Path instance and initialize appropriately.
        path = RtcPath(None, rt_nlri, 0, is_withdraw=is_withdraw,
                       pattrs=pattrs)
        tm = self._core_service.table_manager
        tm.learn_path(path)
Beispiel #6
0
    def get_configured_capabilites(self):
        """Returns configured capabilities."""

        capabilities = OrderedDict()
        mbgp_caps = []
        if self.cap_mbgp_ipv4:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(RF_IPv4_UC.afi,
                                                   RF_IPv4_UC.safi))

        if self.cap_mbgp_ipv6:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(RF_IPv6_UC.afi,
                                                   RF_IPv6_UC.safi))

        if self.cap_mbgp_vpnv4:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(RF_IPv4_VPN.afi,
                                                   RF_IPv4_VPN.safi))

        if self.cap_mbgp_vpnv6:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(RF_IPv6_VPN.afi,
                                                   RF_IPv6_VPN.safi))

        if self.cap_rtc:
            mbgp_caps.append(
                BGPOptParamCapabilityMultiprotocol(RF_RTC_UC.afi,
                                                   RF_RTC_UC.safi))

        if mbgp_caps:
            capabilities[BGP_CAP_MULTIPROTOCOL] = mbgp_caps

        if self.cap_refresh:
            capabilities[BGP_CAP_ROUTE_REFRESH] = [
                BGPOptParamCapabilityRouteRefresh()
            ]

        if self.cap_enhanced_refresh:
            capabilities[BGP_CAP_ENHANCED_ROUTE_REFRESH] = [
                BGPOptParamCapabilityEnhancedRouteRefresh()
            ]

        if self.enable_uri:
            capabilities[ENABLE_URI] = [BGPOptParamCapabilityEnableUri()]

        return capabilities
Beispiel #7
0
    def __init__(self, source, nlri, src_ver_num, pattrs=None, nexthop=None,
                 is_withdraw=False, med_set_by_target_neighbor=False):
        """Initializes Ipv4 path.

        If this path is not a withdraw, then path attribute and nexthop both
        should be provided.
        Parameters:
            - `source`: (Peer/str) source of this path.
            - `nlri`: (Vpnv4) Nlri instance for Vpnv4 route family.
            - `src_ver_num`: (int) version number of *source* when this path
            was learned.
            - `pattrs`: (OrderedDict) various path attributes for this path.
            - `nexthop`: (str) nexthop advertised for this path.
            - `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:
            raise ValueError('NLRI and Path route families do not'
                             ' match (%s, %s).' %
                             (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.
        # Paths can be exported from one VRF and then imported into another
        # VRF, in such cases it source is denoted as string VPN_TABLE.
        if not (source is None or
                hasattr(source, 'version_num') or
                source in (VRF_TABLE, VPN_TABLE)):
            raise ValueError('Invalid or Unsupported source for path: %s' %
                             source)

        # If this path is not a withdraw path, than it should have path-
        # attributes and nexthop.
        if not is_withdraw and not (pattrs and nexthop):
            raise ValueError('Need to provide nexthop and patattrs '
                             'for path that is not a withdraw.')

        # The entity (peer) that gave us this path.
        self._source = source

        # Path attribute of this path.
        if pattrs:
            self._path_attr_map = copy(pattrs)
        else:
            self._path_attr_map = OrderedDict()

        # NLRI that this path represents.
        self._nlri = nlri

        # If given nlri is withdrawn.
        self._is_withdraw = is_withdraw

        # @see Source.version_num
        self._source_version_num = src_ver_num

        self._nexthop = nexthop

        # Automatically generated.
        #
        # self.next_path
        # self.prev_path

        # The Destination from which this path was exported, if any.
        self._exported_from = None
Beispiel #8
0
class Path(object):
    """Represents a way of reaching an IP destination.

    Also contains other meta-data given to us by a specific source (such as a
    peer).
    """
    __metaclass__ = ABCMeta
    __slots__ = ('_source', '_path_attr_map', '_nlri', '_source_version_num',
                 '_exported_from', '_nexthop', 'next_path', 'prev_path',
                 '_is_withdraw', 'med_set_by_target_neighbor')
    ROUTE_FAMILY = RF_IPv4_UC

    def __init__(self, source, nlri, src_ver_num, pattrs=None, nexthop=None,
                 is_withdraw=False, med_set_by_target_neighbor=False):
        """Initializes Ipv4 path.

        If this path is not a withdraw, then path attribute and nexthop both
        should be provided.
        Parameters:
            - `source`: (Peer/str) source of this path.
            - `nlri`: (Vpnv4) Nlri instance for Vpnv4 route family.
            - `src_ver_num`: (int) version number of *source* when this path
            was learned.
            - `pattrs`: (OrderedDict) various path attributes for this path.
            - `nexthop`: (str) nexthop advertised for this path.
            - `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:
            raise ValueError('NLRI and Path route families do not'
                             ' match (%s, %s).' %
                             (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.
        # Paths can be exported from one VRF and then imported into another
        # VRF, in such cases it source is denoted as string VPN_TABLE.
        if not (source is None or
                hasattr(source, 'version_num') or
                source in (VRF_TABLE, VPN_TABLE)):
            raise ValueError('Invalid or Unsupported source for path: %s' %
                             source)

        # If this path is not a withdraw path, than it should have path-
        # attributes and nexthop.
        if not is_withdraw and not (pattrs and nexthop):
            raise ValueError('Need to provide nexthop and patattrs '
                             'for path that is not a withdraw.')

        # The entity (peer) that gave us this path.
        self._source = source

        # Path attribute of this path.
        if pattrs:
            self._path_attr_map = copy(pattrs)
        else:
            self._path_attr_map = OrderedDict()

        # NLRI that this path represents.
        self._nlri = nlri

        # If given nlri is withdrawn.
        self._is_withdraw = is_withdraw

        # @see Source.version_num
        self._source_version_num = src_ver_num

        self._nexthop = nexthop

        # Automatically generated.
        #
        # self.next_path
        # self.prev_path

        # The Destination from which this path was exported, if any.
        self._exported_from = None

    @property
    def source_version_num(self):
        return self._source_version_num

    @property
    def source(self):
        return self._source

    @property
    def route_family(self):
        return self.__class__.ROUTE_FAMILY

    @property
    def nlri(self):
        return self._nlri

    @property
    def is_withdraw(self):
        return self._is_withdraw

    @property
    def pathattr_map(self):
        return copy(self._path_attr_map)

    @property
    def nexthop(self):
        return self._nexthop

    def get_pattr(self, pattr_type, default=None):
        """Returns path attribute of given type.

        Returns None if we do not attribute of type *pattr_type*.
        """
        return self._path_attr_map.get(pattr_type, default)

    def clone(self, for_withdrawal=False):
        pathattrs = None
        if not for_withdrawal:
            pathattrs = self.pathattr_map
        clone = self.__class__(
            self.source,
            self.nlri,
            self.source_version_num,
            pattrs=pathattrs,
            nexthop=self.nexthop,
            is_withdraw=for_withdrawal
        )
        return clone

    def get_rts(self):
        extcomm_attr = self._path_attr_map.get(
            BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
        if extcomm_attr is None:
            rts = []
        else:
            rts = extcomm_attr.rt_list
        return rts

    def has_rts_in(self, interested_rts):
        """Returns True if this `Path` has any `ExtCommunity` attribute
        route target common with `interested_rts`.
        """
        assert isinstance(interested_rts, set)
        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(RouteTargetMembershipNLRI.DEFAULT_RT)

        return not interested_rts.isdisjoint(curr_rts)

    def __str__(self):
        return (
            'Path(source: %s, nlri: %s, source ver#: %s, '
            'path attrs.: %s, nexthop: %s, is_withdraw: %s)' %
            (
                self._source, self._nlri, self._source_version_num,
                self._path_attr_map, self._nexthop, self._is_withdraw
            )
        )

    def __repr__(self):
        return ('Path(%s, %s, %s, %s, %s, %s)' % (
            self._source, self._nlri, self._source_version_num,
            self._path_attr_map, self._nexthop, self._is_withdraw))
Beispiel #9
0
    def insert_vrf_path(self,
                        nlri,
                        next_hop=None,
                        gen_lbl=False,
                        is_withdraw=False,
                        **kwargs):
        assert nlri
        pattrs = None
        label_list = []
        vrf_conf = self.vrf_conf
        if not is_withdraw:
            table_manager = self._core_service.table_manager
            if gen_lbl and next_hop:
                # Label per next_hop demands we use a different label
                # per next_hop. Here connected interfaces are advertised per
                # VRF.
                label_key = (vrf_conf.route_dist, next_hop)
                nh_label = table_manager.get_nexthop_label(label_key)
                if not nh_label:
                    nh_label = table_manager.get_next_vpnv4_label()
                    table_manager.set_nexthop_label(label_key, nh_label)
                label_list.append(nh_label)

            elif gen_lbl:
                # If we do not have next_hop, get a new label.
                label_list.append(table_manager.get_next_vpnv4_label())

            # Set MPLS labels with the generated labels
            if gen_lbl and isinstance(nlri, EvpnMacIPAdvertisementNLRI):
                nlri.mpls_labels = label_list[:2]
            elif gen_lbl and isinstance(nlri, EvpnIpPrefixNLRI):
                nlri.mpls_label = label_list[0]

            # Create a dictionary for path-attrs.
            pattrs = OrderedDict()

            # MpReachNlri and/or MpUnReachNlri attribute info. is contained
            # in the path. Hence we do not add these attributes here.
            from ryu.services.protocols.bgp.core import EXPECTED_ORIGIN

            pattrs[BGP_ATTR_TYPE_ORIGIN] = BGPPathAttributeOrigin(
                EXPECTED_ORIGIN)
            pattrs[BGP_ATTR_TYPE_AS_PATH] = BGPPathAttributeAsPath([])
            communities = []

            # Set ES-Import Route Target
            if isinstance(nlri, EvpnEthernetSegmentNLRI):
                subtype = 2
                es_import = nlri.esi.mac_addr
                communities.append(
                    BGPEvpnEsImportRTExtendedCommunity(subtype=subtype,
                                                       es_import=es_import))

            for rt in vrf_conf.export_rts:
                communities.append(create_rt_extended_community(rt, 2))
            for soo in vrf_conf.soo_list:
                communities.append(create_rt_extended_community(soo, 3))

            # Set Tunnel Encapsulation Attribute
            tunnel_type = kwargs.get('tunnel_type', None)
            if tunnel_type:
                communities.append(
                    BGPEncapsulationExtendedCommunity.from_str(tunnel_type))

            # Set ESI Label Extended Community
            redundancy_mode = kwargs.get('redundancy_mode', None)
            if redundancy_mode is not None:
                subtype = 1
                flags = 0

                from ryu.services.protocols.bgp.api.prefix import (
                    REDUNDANCY_MODE_SINGLE_ACTIVE)
                if redundancy_mode == REDUNDANCY_MODE_SINGLE_ACTIVE:
                    flags |= BGPEvpnEsiLabelExtendedCommunity.SINGLE_ACTIVE_BIT

                vni = kwargs.get('vni', None)
                if vni is not None:
                    communities.append(
                        BGPEvpnEsiLabelExtendedCommunity(subtype=subtype,
                                                         flags=flags,
                                                         vni=vni))
                else:
                    communities.append(
                        BGPEvpnEsiLabelExtendedCommunity(
                            subtype=subtype,
                            flags=flags,
                            mpls_label=label_list[0]))

            pattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = \
                BGPPathAttributeExtendedCommunities(communities=communities)
            if vrf_conf.multi_exit_disc:
                pattrs[BGP_ATTR_TYPE_MULTI_EXIT_DISC] = \
                    BGPPathAttributeMultiExitDisc(vrf_conf.multi_exit_disc)

            # Set PMSI Tunnel Attribute
            pmsi_tunnel_type = kwargs.get('pmsi_tunnel_type', None)
            if pmsi_tunnel_type is not None:
                from ryu.services.protocols.bgp.api.prefix import (
                    PMSI_TYPE_INGRESS_REP)
                if pmsi_tunnel_type == PMSI_TYPE_INGRESS_REP:
                    tunnel_id = PmsiTunnelIdIngressReplication(
                        tunnel_endpoint_ip=self._core_service.router_id)
                else:  # pmsi_tunnel_type == PMSI_TYPE_NO_TUNNEL_INFO
                    tunnel_id = None
                pattrs[BGP_ATTR_TYEP_PMSI_TUNNEL_ATTRIBUTE] = \
                    BGPPathAttributePmsiTunnel(pmsi_flags=0,
                                               tunnel_type=pmsi_tunnel_type,
                                               tunnel_id=tunnel_id,
                                               vni=kwargs.get('vni', None))

        puid = self.VRF_PATH_CLASS.create_puid(vrf_conf.route_dist,
                                               nlri.prefix)

        path = self.VRF_PATH_CLASS(puid,
                                   None,
                                   nlri,
                                   0,
                                   pattrs=pattrs,
                                   nexthop=next_hop,
                                   label_list=label_list,
                                   is_withdraw=is_withdraw)

        # Insert the path into VRF table, get affected destination so that we
        # can process it further.
        eff_dest = self.insert(path)
        # Enqueue the eff_dest for further processing.
        self._signal_bus.dest_changed(eff_dest)
        return label_list
Beispiel #10
0
    def insert_vrf_path(self,
                        nlri,
                        next_hop=None,
                        gen_lbl=False,
                        is_withdraw=False,
                        **kwargs):
        assert nlri
        pattrs = None
        label_list = []
        vrf_conf = self.vrf_conf
        if not is_withdraw:
            # Create a dictionary for path-attrs.
            pattrs = OrderedDict()

            # MpReachNlri and/or MpUnReachNlri attribute info. is contained
            # in the path. Hence we do not add these attributes here.
            from ryu.services.protocols.bgp.core import EXPECTED_ORIGIN

            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 = soo.split(':')
                subtype = 3
                communities.append(
                    BGPTwoOctetAsSpecificExtendedCommunity(
                        as_number=int(as_num),
                        local_administrator=int(local_admin),
                        subtype=subtype))

            # Set Tunnel Encapsulation Attribute
            tunnel_type = kwargs.get('tunnel_type', None)
            if tunnel_type:
                communities.append(
                    BGPEncapsulationExtendedCommunity.from_str(tunnel_type))

            pattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = \
                BGPPathAttributeExtendedCommunities(communities=communities)
            if 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:
                # Label per next_hop demands we use a different label
                # per next_hop. Here connected interfaces are advertised per
                # VRF.
                label_key = (vrf_conf.route_dist, next_hop)
                nh_label = table_manager.get_nexthop_label(label_key)
                if not nh_label:
                    nh_label = table_manager.get_next_vpnv4_label()
                    table_manager.set_nexthop_label(label_key, nh_label)
                label_list.append(nh_label)

            elif gen_lbl:
                # If we do not have next_hop, get a new label.
                label_list.append(table_manager.get_next_vpnv4_label())

            # Set PMSI Tunnel Attribute
            pmsi_tunnel_type = kwargs.get('pmsi_tunnel_type', None)
            if pmsi_tunnel_type is not None:
                from ryu.services.protocols.bgp.api.prefix import (
                    PMSI_TYPE_INGRESS_REP)
                if pmsi_tunnel_type == PMSI_TYPE_INGRESS_REP:
                    tunnel_id = PmsiTunnelIdIngressReplication(
                        tunnel_endpoint_ip=self._core_service.router_id)
                else:  # pmsi_tunnel_type == PMSI_TYPE_NO_TUNNEL_INFO
                    tunnel_id = None
                pattrs[BGP_ATTR_TYEP_PMSI_TUNNEL_ATTRIBUTE] = \
                    BGPPathAttributePmsiTunnel(pmsi_flags=0,
                                               tunnel_type=pmsi_tunnel_type,
                                               tunnel_id=tunnel_id)

            # Set MPLS labels with the generated labels
            if gen_lbl and isinstance(nlri, EvpnMacIPAdvertisementNLRI):
                nlri.mpls_labels = label_list[:2]

        puid = self.VRF_PATH_CLASS.create_puid(vrf_conf.route_dist,
                                               nlri.prefix)

        path = self.VRF_PATH_CLASS(puid,
                                   None,
                                   nlri,
                                   0,
                                   pattrs=pattrs,
                                   nexthop=next_hop,
                                   label_list=label_list,
                                   is_withdraw=is_withdraw)

        # Insert the path into VRF table, get affected destination so that we
        # can process it further.
        eff_dest = self.insert(path)
        # Enqueue the eff_dest for further processing.
        self._signal_bus.dest_changed(eff_dest)
        return label_list