Exemplo n.º 1
0
Arquivo: nlri.py Projeto: alextwl/ryu
    def __init__(self, labels, route_disc, prefix):
        Nlri.__init__(self)
        if not labels:
            labels = []

        # Validate given params
        for label in labels:
            if not is_valid_mpls_label(label):
                raise ValueError('Invalid label %s' % label)
        if (not is_valid_route_disc(route_disc) or
                not is_valid_ipv6_prefix(prefix)):
            raise ValueError('Invalid parameter value(s).')

        self._labels = labels
        self._route_disc = route_disc
        self._prefix = prefix
Exemplo n.º 2
0
    def add_to_vrf(self, route_dist, prefix, next_hop, route_family):
        """Adds `prefix` to VRF identified by `route_dist` with given
         `next_hop`.

        Returns assigned VPN label.
        """
        from ryu.services.protocols.bgp.core import BgpCoreError

        assert route_dist and prefix and next_hop
        if route_family not in (VRF_RF_IPV4, VRF_RF_IPV6):
            raise ValueError('Given route_family %s is not supported.' %
                             route_family)

        vrf_table = None
        table_id = (route_dist, route_family)
        if route_family == VRF_RF_IPV4:
            vrf_table = self._tables.get(table_id)
            if vrf_table is None:
                raise BgpCoreError(desc='VRF table for RD: %s does not '
                                        '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)
        elif route_family == VRF_RF_IPV6:
            vrf_table = self._tables.get(table_id)
            if vrf_table is None:
                raise BgpCoreError(desc='VRF table for RD: %s does not '
                                        '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)

        return vrf_table.insert_vrf_path(
            prefix, next_hop=next_hop,
            gen_lbl=True
        )
Exemplo n.º 3
0
    def remove_from_vrf(self, route_dist, prefix, route_family):
        """Removes `prefix` from VRF identified by `route_dist`.

        Returns assigned VPN label.
        """
        from ryu.services.protocols.bgp.core import BgpCoreError
        # Validate given
        if route_family not in (VRF_RF_IPV4, VRF_RF_IPV6):
            raise BgpCoreError(desc='Unsupported route family %s' %
                                    route_family)
        val_ipv4 = route_family == VRF_RF_IPV4\
            and is_valid_ipv4_prefix(prefix)
        val_ipv6 = route_family == VRF_RF_IPV6\
            and is_valid_ipv6_prefix(prefix)

        if not val_ipv4 and not val_ipv6:
            raise BgpCoreError(desc='Invalid prefix or nexthop.')

        table_id = (route_dist, route_family)
        if route_family == VRF_RF_IPV4:
            vrf_table = self._tables.get(table_id)
            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)
        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)
            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)
Exemplo n.º 4
0
def is_valid_ip_prefix(prefix):
    if not (validation.is_valid_ipv4_prefix(prefix)
            or validation.is_valid_ipv6_prefix(prefix)):
        raise ConfigValueError(conf_name=IP_PREFIX,
                               conf_value=prefix)
Exemplo n.º 5
0
    def update_vrf_table(self, route_dist, prefix=None, next_hop=None,
                         route_family=None, route_type=None, tunnel_type=None,
                         is_withdraw=False, redundancy_mode=None,
                         pmsi_tunnel_type=None, **kwargs):
        """Update a BGP route in the VRF table identified by `route_dist`
        with the given `next_hop`.

        If `is_withdraw` is False, which is the default, add a BGP route
        to the VRF table identified by `route_dist` with the given
        `next_hop`.
        If `is_withdraw` is True, remove a BGP route from the VRF table
        and the given `next_hop` is ignored.

        If `route_family` is VRF_RF_L2_EVPN, `route_type` and `kwargs`
        are required to construct EVPN NLRI and `prefix` is ignored.

        ``redundancy_mode`` specifies a redundancy mode type.

`       `pmsi_tunnel_type` specifies the type of the PMSI tunnel attribute
         used to encode the multicast tunnel identifier.
        This field is advertised only if route_type is
        EVPN_MULTICAST_ETAG_ROUTE.

        Returns assigned VPN label.
        """
        from ryu.services.protocols.bgp.core import BgpCoreError

        assert route_dist

        if is_withdraw:
            gen_lbl = False
            next_hop = None
        else:
            gen_lbl = True
            if not (is_valid_ipv4(next_hop) or is_valid_ipv6(next_hop)):
                raise BgpCoreError(
                    desc='Invalid IPv4/IPv6 nexthop: %s' % next_hop)

        vrf_table = self._tables.get((route_dist, route_family))
        if vrf_table is None:
            raise BgpCoreError(
                desc='VRF table  does not exist: route_dist=%s, '
                     'route_family=%s' % (route_dist, route_family))

        vni = kwargs.get('vni', None)

        if route_family == VRF_RF_IPV4:
            if not is_valid_ipv4_prefix(prefix):
                raise BgpCoreError(desc='Invalid IPv4 prefix: %s' % prefix)
            ip, masklen = prefix.split('/')
            prefix = IPAddrPrefix(int(masklen), ip)
        elif route_family == VRF_RF_IPV6:
            if not is_valid_ipv6_prefix(prefix):
                raise BgpCoreError(desc='Invalid IPv6 prefix: %s' % prefix)
            ip6, masklen = prefix.split('/')
            prefix = IP6AddrPrefix(int(masklen), ip6)
        elif route_family == VRF_RF_L2_EVPN:
            assert route_type
            if route_type == EvpnMacIPAdvertisementNLRI.ROUTE_TYPE_NAME:
                # MPLS labels will be assigned automatically
                kwargs['mpls_labels'] = []
            subclass = EvpnNLRI._lookup_type_name(route_type)
            kwargs['route_dist'] = route_dist
            esi = kwargs.get('esi', None)
            if esi is not None:
                if isinstance(esi, dict):
                    esi_type = esi.get('type', 0)
                    esi_class = EvpnEsi._lookup_type(esi_type)
                    kwargs['esi'] = esi_class.from_jsondict(esi)
                else:  # isinstance(esi, numbers.Integral)
                    kwargs['esi'] = EvpnArbitraryEsi(
                        type_desc.Int9.from_user(esi))
            if vni is not None:
                # Disable to generate MPLS labels,
                # because encapsulation type is not MPLS.
                from ryu.services.protocols.bgp.api.prefix import (
                    TUNNEL_TYPE_VXLAN, TUNNEL_TYPE_NVGRE)
                assert tunnel_type in [
                    None, TUNNEL_TYPE_VXLAN, TUNNEL_TYPE_NVGRE]
                gen_lbl = False
            prefix = subclass(**kwargs)
        else:
            raise BgpCoreError(
                desc='Unsupported route family %s' % route_family)

        # 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(
            nlri=prefix, next_hop=next_hop, gen_lbl=gen_lbl,
            is_withdraw=is_withdraw, redundancy_mode=redundancy_mode,
            vni=vni, tunnel_type=tunnel_type,
            pmsi_tunnel_type=pmsi_tunnel_type)
Exemplo n.º 6
0
    def update_vrf_table(self, route_dist, prefix=None, next_hop=None,
                         route_family=None, route_type=None, tunnel_type=None,
                         is_withdraw=False, **kwargs):
        """Update a BGP route in the VRF table identified by `route_dist`
        with the given `next_hop`.

        If `is_withdraw` is False, which is the default, add a BGP route
        to the VRF table identified by `route_dist` with the given
        `next_hop`.
        If `is_withdraw` is True, remove a BGP route from the VRF table
        and the given `next_hop` is ignored.

        If `route_family` is VRF_RF_L2_EVPN, `route_type` and `kwargs`
        are required to construct EVPN NLRI and `prefix` is ignored.

        Returns assigned VPN label.
        """
        from ryu.services.protocols.bgp.core import BgpCoreError

        assert route_dist

        if is_withdraw:
            gen_lbl = False
            next_hop = None
        else:
            gen_lbl = True
            if not (is_valid_ipv4(next_hop) or is_valid_ipv6(next_hop)):
                raise BgpCoreError(
                    desc='Invalid IPv4/IPv6 nexthop: %s' % next_hop)

        vrf_table = self._tables.get((route_dist, route_family))
        if vrf_table is None:
            raise BgpCoreError(
                desc='VRF table  does not exist: route_dist=%s, '
                     'route_family=%s' % (route_dist, route_family))

        if route_family == VRF_RF_IPV4:
            if not is_valid_ipv4_prefix(prefix):
                raise BgpCoreError(desc='Invalid IPv4 prefix: %s' % prefix)
            ip, masklen = prefix.split('/')
            prefix = IPAddrPrefix(int(masklen), ip)
        elif route_family == VRF_RF_IPV6:
            if not is_valid_ipv6_prefix(prefix):
                raise BgpCoreError(desc='Invalid IPv6 prefix: %s' % prefix)
            ip6, masklen = prefix.split('/')
            prefix = IP6AddrPrefix(int(masklen), ip6)
        elif route_family == VRF_RF_L2_EVPN:
            assert route_type
            if route_type == EvpnMacIPAdvertisementNLRI.ROUTE_TYPE_NAME:
                # MPLS labels will be assigned automatically
                kwargs['mpls_labels'] = []
            subclass = EvpnNLRI._lookup_type_name(route_type)
            kwargs['route_dist'] = route_dist
            esi = kwargs.get('esi', None)
            if esi is not None:
                # Note: Currently, we support arbitrary 9-octet ESI value only.
                kwargs['esi'] = EvpnArbitraryEsi(type_desc.Int9.from_user(esi))
            if 'vni' in kwargs:
                # Disable to generate MPLS labels, because encapsulation type
                # is not MPLS.
                from ryu.services.protocols.bgp.api.prefix import (
                    TUNNEL_TYPE_VXLAN, TUNNEL_TYPE_NVGRE)
                assert tunnel_type in [TUNNEL_TYPE_VXLAN, TUNNEL_TYPE_NVGRE]
                gen_lbl = False
            prefix = subclass(**kwargs)
        else:
            raise BgpCoreError(
                desc='Unsupported route family %s' % route_family)

        # 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(
            nlri=prefix, next_hop=next_hop, gen_lbl=gen_lbl,
            is_withdraw=is_withdraw, tunnel_type=tunnel_type)
Exemplo n.º 7
0
def is_valid_prefix(prefix):
    if not (validation.is_valid_ipv4_prefix(prefix)
            or validation.is_valid_ipv6_prefix(prefix)):
        raise ConfigValueError(conf_name=PREFIX,
                               conf_value=prefix)
Exemplo n.º 8
0
    def update_vrf_table(self,
                         route_dist,
                         prefix=None,
                         next_hop=None,
                         route_family=None,
                         route_type=None,
                         tunnel_type=None,
                         is_withdraw=False,
                         redundancy_mode=None,
                         pmsi_tunnel_type=None,
                         **kwargs):
        """Update a BGP route in the VRF table identified by `route_dist`
        with the given `next_hop`.

        If `is_withdraw` is False, which is the default, add a BGP route
        to the VRF table identified by `route_dist` with the given
        `next_hop`.
        If `is_withdraw` is True, remove a BGP route from the VRF table
        and the given `next_hop` is ignored.

        If `route_family` is VRF_RF_L2_EVPN, `route_type` and `kwargs`
        are required to construct EVPN NLRI and `prefix` is ignored.

        ``redundancy_mode`` specifies a redundancy mode type.

`       `pmsi_tunnel_type` specifies the type of the PMSI tunnel attribute
         used to encode the multicast tunnel identifier.
        This field is advertised only if route_type is
        EVPN_MULTICAST_ETAG_ROUTE.

        Returns assigned VPN label.
        """
        from ryu.services.protocols.bgp.core import BgpCoreError

        assert route_dist

        if is_withdraw:
            gen_lbl = False
            next_hop = None
        else:
            gen_lbl = True
            if not (is_valid_ipv4(next_hop) or is_valid_ipv6(next_hop)):
                raise BgpCoreError(desc='Invalid IPv4/IPv6 nexthop: %s' %
                                   next_hop)

        vrf_table = self._tables.get((route_dist, route_family))
        if vrf_table is None:
            raise BgpCoreError(
                desc='VRF table  does not exist: route_dist=%s, '
                'route_family=%s' % (route_dist, route_family))

        vni = kwargs.get('vni', None)

        if route_family == VRF_RF_IPV4:
            if not is_valid_ipv4_prefix(prefix):
                raise BgpCoreError(desc='Invalid IPv4 prefix: %s' % prefix)
            ip, masklen = prefix.split('/')
            prefix = IPAddrPrefix(int(masklen), ip)
        elif route_family == VRF_RF_IPV6:
            if not is_valid_ipv6_prefix(prefix):
                raise BgpCoreError(desc='Invalid IPv6 prefix: %s' % prefix)
            ip6, masklen = prefix.split('/')
            prefix = IP6AddrPrefix(int(masklen), ip6)
        elif route_family == VRF_RF_L2_EVPN:
            assert route_type
            if route_type == EvpnMacIPAdvertisementNLRI.ROUTE_TYPE_NAME:
                # MPLS labels will be assigned automatically
                kwargs['mpls_labels'] = []
            if route_type == EvpnInclusiveMulticastEthernetTagNLRI.ROUTE_TYPE_NAME:
                # Inclusive Multicast Ethernet Tag Route does not have "vni",
                # omit "vni" from "kwargs" here.
                vni = kwargs.pop('vni', None)
            subclass = EvpnNLRI._lookup_type_name(route_type)
            kwargs['route_dist'] = route_dist
            esi = kwargs.get('esi', None)
            if esi is not None:
                if isinstance(esi, dict):
                    esi_type = esi.get('type', 0)
                    esi_class = EvpnEsi._lookup_type(esi_type)
                    kwargs['esi'] = esi_class.from_jsondict(esi)
                else:  # isinstance(esi, numbers.Integral)
                    kwargs['esi'] = EvpnArbitraryEsi(
                        type_desc.Int9.from_user(esi))
            if vni is not None:
                # Disable to generate MPLS labels,
                # because encapsulation type is not MPLS.
                from ryu.services.protocols.bgp.api.prefix import (
                    TUNNEL_TYPE_VXLAN, TUNNEL_TYPE_NVGRE)
                assert tunnel_type in [
                    None, TUNNEL_TYPE_VXLAN, TUNNEL_TYPE_NVGRE
                ]
                gen_lbl = False
            prefix = subclass(**kwargs)
        else:
            raise BgpCoreError(desc='Unsupported route family %s' %
                               route_family)

        # 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(nlri=prefix,
                                         next_hop=next_hop,
                                         gen_lbl=gen_lbl,
                                         is_withdraw=is_withdraw,
                                         redundancy_mode=redundancy_mode,
                                         vni=vni,
                                         tunnel_type=tunnel_type,
                                         pmsi_tunnel_type=pmsi_tunnel_type)
Exemplo n.º 9
0
 def test_is_valid_ipv6_prefix_invalid_addr(self):
     eq_(False, validation.is_valid_ipv6_prefix("xxxx::xxxx/64"))
Exemplo n.º 10
0
 def test_is_valid_ipv6_prefix_without_prefix(self):
     eq_(False, validation.is_valid_ipv6_prefix("fe80::0011:aabb:ccdd:eeff"))
Exemplo n.º 11
0
 def test_is_valid_ipv6_prefix_not_str(self):
     eq_(False, validation.is_valid_ipv6_prefix(1234))
Exemplo n.º 12
0
 def test_is_valid_ipv6_prefix(self):
     ok_(validation.is_valid_ipv6_prefix("fe80::0011:aabb:ccdd:eeff/64"))
Exemplo n.º 13
0
Arquivo: nlri.py Projeto: alextwl/ryu
 def __init__(self, prefix):
     if not is_valid_ipv6_prefix(prefix):
         raise ValueError('Invalid prefix %s.' % prefix)
     Nlri.__init__(self)
     self._prefix = prefix