Beispiel #1
0
    def configure_vpp_nsim(node, vpp_nsim_attr, interface0, interface1=None):
        """Configure nsim on the specified VPP node.

        :param node: Topology node.
        :param vpp_nsim_attr: VPP NSIM configuration attributes
        :param interface0: Interface name.
        :param interface1: 2nd Interface name for cross-connect feature
        :type node: dict
        :type vpp_nsim_attr: dict
        :type interface0: str or int
        :type interface1: str or int
        :raises RuntimeError: if no NSIM features are enabled or
                vpp papi command fails.
        """
        host = node[u"host"]
        if not vpp_nsim_attr[u"output_nsim_enable"] \
                and not vpp_nsim_attr[u"xc_nsim_enable"]:
            raise RuntimeError(f"No NSIM features enabled on host {host}:\n"
                               f"vpp_nsim_attr = {vpp_nsim_attr}")
        cmd = u"nsim_configure2"
        args = dict(delay_in_usec=vpp_nsim_attr[u"delay_in_usec"],
                    average_packet_size=vpp_nsim_attr[u"average_packet_size"],
                    bandwidth_in_bits_per_second=vpp_nsim_attr[
                        u"bw_in_bits_per_second"],
                    packets_per_drop=vpp_nsim_attr[u"packets_per_drop"],
                    packets_per_reorder=vpp_nsim_attr.get(
                        u"packets_per_reorder", 0))
        err_msg = f"Failed to configure NSIM on host {host}"
        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)

        if vpp_nsim_attr[u"output_nsim_enable"]:
            cmd = u"nsim_output_feature_enable_disable"
            args = dict(
                enable_disable=vpp_nsim_attr[u"output_nsim_enable"],
                sw_if_index=InterfaceUtil.get_interface_index(
                    node, interface0),
            )
            err_msg = f"Failed to enable NSIM output feature on " \
                f"host {host} interface {interface0}"
            with PapiSocketExecutor(node) as papi_exec:
                papi_exec.add(cmd, **args).get_reply(err_msg)

        elif vpp_nsim_attr[u"xc_nsim_enable"]:
            cmd = u"nsim_cross_connect_feature_enable_disable"
            args = dict(
                enable_disable=vpp_nsim_attr[u"xc_nsim_enable"],
                sw_if_index0=InterfaceUtil.get_interface_index(
                    node, interface0),
                sw_if_index1=InterfaceUtil.get_interface_index(
                    node, interface1),
            )
            err_msg = f"Failed to enable NSIM output feature on " \
                f"host {host} interface {interface0}"
            with PapiSocketExecutor(node) as papi_exec:
                papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #2
0
    def get_interface_vrf_table(node, interface, ip_version='ipv4'):
        """Get vrf ID for the given interface.

        :param node: VPP node.
        :param interface: Name or sw_if_index of a specific interface.
        :type node: dict
        :param ip_version: IP protocol version (ipv4 or ipv6).
        :type interface: str or int
        :type ip_version: str
        :returns: vrf ID of the specified interface.
        :rtype: int
        """
        sw_if_index = InterfaceUtil.get_interface_index(node, interface)

        cmd = u"sw_interface_get_table"
        args = dict(
            sw_if_index=sw_if_index,
            is_ipv6=bool(ip_version == u"ipv6")
        )
        err_msg = f"Failed to get VRF id assigned to interface {interface}"

        with PapiSocketExecutor(node) as papi_exec:
            reply = papi_exec.add(cmd, **args).get_reply(err_msg)

        return reply[u"vrf_id"]
Beispiel #3
0
    def vpp_interface_set_ip_address(node,
                                     interface,
                                     address,
                                     prefix_length=None):
        """Set IP address to VPP interface.

        :param node: VPP node.
        :param interface: Interface name.
        :param address: IP address.
        :param prefix_length: Prefix length.
        :type node: dict
        :type interface: str
        :type address: str
        :type prefix_length: int
        """
        ip_addr = ip_address(address)

        cmd = u"sw_interface_add_del_address"
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    is_add=True,
                    del_all=False,
                    prefix=IPUtil.create_prefix_object(
                        ip_addr, prefix_length if prefix_length else
                        128 if ip_addr.version == 6 else 32))
        err_msg = f"Failed to add IP address on interface {interface}"

        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #4
0
    def vpp_get_interface_ip_addresses(node, interface, ip_version):
        """Get list of IP addresses from an interface on a VPP node.

        :param node: VPP node.
        :param interface: Name of an interface on the VPP node.
        :param ip_version: IP protocol version (ipv4 or ipv6).
        :type node: dict
        :type interface: str
        :type ip_version: str
        :returns: List of dictionaries, each containing IP address, subnet
            prefix length and also the subnet mask for ipv4 addresses.
            Note: A single interface may have multiple IP addresses assigned.
        :rtype: list
        """
        sw_if_index = InterfaceUtil.get_interface_index(node, interface)

        if not sw_if_index:
            return list()

        cmd = u"ip_address_dump"
        args = dict(sw_if_index=sw_if_index,
                    is_ipv6=bool(ip_version == u"ipv6"))
        err_msg = f"Failed to get L2FIB dump on host {node[u'host']}"

        with PapiSocketExecutor(node) as papi_exec:
            details = papi_exec.add(cmd, **args).get_details(err_msg)

        # TODO: CSIT currently looks only whether the list is empty.
        # Add proper value processing if values become important.

        return details
Beispiel #5
0
    def get_interface_vrf_table(node, interface, ip_version='ipv4'):
        """Get vrf ID for the given interface.

        :param node: VPP node.
        :param interface: Name or sw_if_index of a specific interface.
        :type node: dict
        :param ip_version: IP protocol version (ipv4 or ipv6).
        :type interface: str or int
        :type ip_version: str
        :returns: vrf ID of the specified interface.
        :rtype: int
        """
        sw_if_index = InterfaceUtil.get_interface_index(node, interface)

        is_ipv6 = 1 if ip_version == 'ipv6' else 0

        cmd = 'sw_interface_get_table'
        args = dict(sw_if_index=sw_if_index, is_ipv6=is_ipv6)
        err_msg = 'Failed to get VRF id assigned to interface {ifc}'.format(
            ifc=interface)

        with PapiExecutor(node) as papi_exec:
            reply = papi_exec.add(cmd, **args).get_reply(err_msg)

        return reply['vrf_id']
Beispiel #6
0
    def vpp_interface_set_ip_address(node,
                                     interface,
                                     address,
                                     prefix_length=None):
        """Set IP address to VPP interface.

        :param node: VPP node.
        :param interface: Interface name.
        :param address: IP address.
        :param prefix_length: Prefix length.
        :type node: dict
        :type interface: str
        :type address: str
        :type prefix_length: int
        """
        ip_addr = ip_address(unicode(address))

        cmd = 'sw_interface_add_del_address'
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    is_add=1,
                    is_ipv6=1 if ip_addr.version == 6 else 0,
                    del_all=0,
                    address_length=int(prefix_length)
                    if prefix_length else 128 if ip_addr.version == 6 else 32,
                    address=ip_addr.packed)
        err_msg = 'Failed to add IP address on interface {ifc}'.format(
            ifc=interface)
        with PapiExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #7
0
    def _get_sr_steer_policy_args(node,
                                  mode,
                                  interface=None,
                                  ip_addr=None,
                                  prefix=None):
        """Return values of sw_if_index, mask_width, prefix_addr and
            traffic_type for sr_steering_add_del API.

        :param node: Given node to create/delete steering policy on.
        :param mode: Mode of operation - L2 or L3.
        :param interface: Interface name (Optional, required in case of
            L2 mode).
        :param ip_addr: IPv4/IPv6 address (Optional, required in case of L3
            mode).
        :param prefix: IP address prefix (Optional, required in case of L3
            mode).
        :type node: dict
        :type mode: str
        :type interface: str
        :type ip_addr: str
        :type prefix: int
        :returns: Values for sw_if_index, prefix and traffic_type
        :rtype: tuple
        :raises ValueError: If unsupported mode used or required parameter
            is missing.
        """
        if mode.lower() == u"l2":
            if interface is None:
                raise ValueError(f"Required data missing.\n"
                                 f"interface: {interface}")
            sw_if_index = InterfaceUtil.get_interface_index(node, interface)
            prefix = 0
            traffic_type = getattr(SRv6PolicySteeringTypes,
                                   u"SR_STEER_L2").value
        elif mode.lower() == u"l3":
            if ip_addr is None or prefix is None:
                raise ValueError(f"Required data missing.\n"
                                 f"IP address:{ip_addr}\n"
                                 f"mask:{prefix}")
            sw_if_index = Constants.BITWISE_NON_ZERO
            ip_addr = ip_address(ip_addr)
            prefix = IPUtil.create_prefix_object(ip_addr, int(prefix))
            traffic_type = getattr(
                SRv6PolicySteeringTypes,
                u"SR_STEER_IPV4").value if ip_addr.version == 4 else getattr(
                    SRv6PolicySteeringTypes, u"SR_STEER_IPV6").value
        else:
            raise ValueError(f"Unsupported mode: {mode}")

        return sw_if_index, prefix, traffic_type
Beispiel #8
0
    def flush_ip_addresses(node, interface):
        """Flush all IP addresses from specified interface.

        :param node: VPP node.
        :param interface: Interface name.
        :type node: dict
        :type interface: str
        """
        cmd = 'sw_interface_add_del_address'
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    del_all=1)
        err_msg = 'Failed to flush IP address on interface {ifc}'.format(
            ifc=interface)
        with PapiExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #9
0
    def vpp_ip_source_check_setup(node, if_name):
        """Setup Reverse Path Forwarding source check on interface.

        :param node: VPP node.
        :param if_name: Interface name to setup RPF source check.
        :type node: dict
        :type if_name: str
        """
        cmd = u"ip_source_check_interface_add_del"
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, if_name),
                    is_add=1,
                    loose=0)
        err_msg = f"Failed to enable source check on interface {if_name}"
        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #10
0
    def vpp_ra_suppress_link_layer(node, interface):
        """Suppress ICMPv6 router advertisement message for link scope address.

        :param node: VPP node.
        :param interface: Interface name.
        :type node: dict
        :type interface: str
        """
        cmd = 'sw_interface_ip6nd_ra_config'
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    suppress=1)
        err_msg = 'Failed to suppress ICMPv6 router advertisement message on ' \
                  'interface {ifc}'.format(ifc=interface)

        with PapiExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #11
0
    def vpp_proxy_arp_interface_enable(node, interface):
        """Enable proxy ARP on interface.

        :param node: VPP node to enable proxy ARP on interface.
        :param interface: Interface to enable proxy ARP.
        :type node: dict
        :type interface: str or int
        """

        cmd = 'proxy_arp_intfc_enable_disable'
        args = dict(
            sw_if_index=InterfaceUtil.get_interface_index(node, interface),
            enable_disable=1)
        err_msg = 'Failed to enable proxy ARP on interface {ifc}'.format(
            ifc=interface)
        with PapiExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #12
0
    def vpp_ra_suppress_link_layer(node, interface):
        """Suppress ICMPv6 router advertisement message for link scope address.

        :param node: VPP node.
        :param interface: Interface name.
        :type node: dict
        :type interface: str
        """
        cmd = u"sw_interface_ip6nd_ra_config"
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    suppress=1)
        err_msg = f"Failed to suppress ICMPv6 router advertisement message " \
            f"on interface {interface}"

        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #13
0
    def flush_ip_addresses(node, interface):
        """Flush all IP addresses from specified interface.

        :param node: VPP node.
        :param interface: Interface name.
        :type node: dict
        :type interface: str
        """
        cmd = u"sw_interface_add_del_address"
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    is_add=False,
                    del_all=True)
        err_msg = f"Failed to flush IP address on interface {interface}"

        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #14
0
    def vpp_ip_probe(node, interface, addr):
        """Run ip probe on VPP node.

        :param node: VPP node.
        :param interface: Interface key or name.
        :param addr: IPv4/IPv6 address.
        :type node: dict
        :type interface: str
        :type addr: str
        """
        cmd = u"ip_probe_neighbor"
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    dst=str(addr))
        err_msg = f"VPP ip probe {interface} {addr} failed on {node[u'host']}"

        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #15
0
    def vpp_interface_ra_suppress(node, interface):
        """Disable sending ICMPv6 router-advertisement messages on
        an interface on a VPP node.

        :param node: VPP node.
        :param interface: Interface name.
        :type node: dict
        :type interface: str
        """
        cmd = u"sw_interface_ip6nd_ra_config"
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    suppress=1)
        err_msg = f"Failed to disable sending ICMPv6 router-advertisement " \
            f"messages on interface {interface}"

        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #16
0
    def vpp_ip_source_check_setup(node, if_name):
        """Setup Reverse Path Forwarding source check on interface.

        :param node: VPP node.
        :param if_name: Interface name to setup RPF source check.
        :type node: dict
        :type if_name: str
        """
        cmd = 'ip_source_check_interface_add_del'
        args = dict(
            sw_if_index=InterfaceUtil.get_interface_index(node, if_name),
            is_add=1,
            loose=0)
        err_msg = 'Failed to enable source check on interface {ifc}'.format(
            ifc=if_name)
        with PapiExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_replies(err_msg). \
                verify_reply(err_msg=err_msg)
Beispiel #17
0
    def vpp_get_interface_ip_addresses(node, interface, ip_version):
        """Get list of IP addresses from an interface on a VPP node.

        :param node: VPP node.
        :param interface: Name of an interface on the VPP node.
        :param ip_version: IP protocol version (ipv4 or ipv6).
        :type node: dict
        :type interface: str
        :type ip_version: str
        :returns: List of dictionaries, each containing IP address, subnet
            prefix length and also the subnet mask for ipv4 addresses.
            Note: A single interface may have multiple IP addresses assigned.
        :rtype: list
        """
        sw_if_index = InterfaceUtil.get_interface_index(node, interface)

        data = list()
        if sw_if_index:
            is_ipv6 = 1 if ip_version == 'ipv6' else 0

            cmd = 'ip_address_dump'
            cmd_reply = 'ip_address_details'
            args = dict(sw_if_index=sw_if_index,
                        is_ipv6=is_ipv6)
            err_msg = 'Failed to get L2FIB dump on host {host}'.format(
                host=node['host'])

            with PapiExecutor(node) as papi_exec:
                papi_resp = papi_exec.add(cmd, **args).get_dump(err_msg)

            for item in papi_resp.reply[0]['api_reply']:
                item[cmd_reply]['ip'] = item[cmd_reply]['prefix'].split('/')[0]
                item[cmd_reply]['prefix_length'] = int(
                    item[cmd_reply]['prefix'].split('/')[1])
                item[cmd_reply]['is_ipv6'] = is_ipv6
                item[cmd_reply]['netmask'] = \
                    str(IPv6Network(unicode('::/{pl}'.format(
                        pl=item[cmd_reply]['prefix_length']))).netmask) \
                    if is_ipv6 \
                    else str(IPv4Network(unicode('0.0.0.0/{pl}'.format(
                        pl=item[cmd_reply]['prefix_length']))).netmask)
                data.append(item[cmd_reply])

        return data
Beispiel #18
0
    def set_acl_list_for_interface(node, interface, acl_type, acl_idx=None):
        """Set the list of input or output ACLs applied to the interface. It
        unapplies any previously applied ACLs.

        :param node: VPP node to set ACL on.
        :param interface: Interface name or sw_if_index.
        :param acl_type: Type of ACL(s) - input or output.
        :param acl_idx: Index(ies) of ACLs to be applied on the interface.
        :type node: dict
        :type interface: str or int
        :type acl_type: str
        :type acl_idx: list
        """
        Classify._acl_interface_set_acl_list(
            node=node,
            sw_if_index=int(InterfaceUtil.get_interface_index(node,
                                                              interface)),
            acl_type=acl_type,
            acls=acl_idx if isinstance(acl_idx, list) else list())
Beispiel #19
0
    def vpp_ip_probe(node, interface, addr):
        """Run ip probe on VPP node.

        :param node: VPP node.
        :param interface: Interface key or name.
        :param addr: IPv4/IPv6 address.
        :type node: dict
        :type interface: str
        :type addr: str
        """
        cmd = 'ip_probe_neighbor'
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    dst=str(addr))
        err_msg = 'VPP ip probe {dev} {ip} failed on {h}'.format(
            dev=interface, ip=addr, h=node['host'])

        with PapiExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #20
0
    def vpp_ra_send_after_interval(node, interface, interval=2):
        """Setup vpp router advertisement(RA) in such way it sends RA packet
        after every interval value.

        :param node: VPP node.
        :param interface: Interface name.
        :param interval: Interval in seconds for RA resend.
        :type node: dict
        :type interface: str
        :type interval: int
        """
        cmd = u"sw_interface_ip6nd_ra_config"
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    initial_interval=int(interval))
        err_msg = f"Failed to set router advertisement interval " \
            f"on interface {interface}"

        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #21
0
    def vpp_ra_send_after_interval(node, interface, interval=2):
        """Setup vpp router advertisement(RA) in such way it sends RA packet
        after every interval value.

        :param node: VPP node.
        :param interface: Interface name.
        :param interval: Interval in seconds for RA resend.
        :type node: dict
        :type interface: str
        :type interval: int
        """
        cmd = 'sw_interface_ip6nd_ra_config'
        args = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface),
                    initial_interval=int(interval))
        err_msg = 'Failed to set router advertisement interval on ' \
                  'interface {ifc}'.format(ifc=interface)

        with PapiExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_replies(err_msg). \
                verify_reply(err_msg=err_msg)
Beispiel #22
0
    def add_del_macip_acl_interface(node, interface, action, acl_idx):
        """Apply/un-apply the MACIP ACL to/from a given interface.

        :param node: VPP node to set MACIP ACL on.
        :param interface: Interface name or sw_if_index.
        :param action: Required action - add or del.
        :param acl_idx: ACL index to be applied on the interface.
        :type node: dict
        :type interface: str or int
        :type action: str
        :type acl_idx: str or int
        :raises RuntimeError: If unable to set MACIP ACL for the interface.
        """
        cmd = u"macip_acl_interface_add_del"
        err_msg = f"Failed to get 'macip_acl_interface' on host {node[u'host']}"
        args = dict(is_add=bool(action == u"add"),
                    sw_if_index=int(
                        InterfaceUtil.get_interface_index(node, interface)),
                    acl_index=int(acl_idx))
        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #23
0
    def vpp_create_vxlan_and_vlan_interfaces(
            node, node_vxlan_if, node_vlan_if, vxlan_count, vni_start,
            src_ip_start, dst_ip_start, ip_step):
        """
        Configure IPs, create VXLAN interfaces and VLAN sub-interfaces on VPP
        node.

        :param node: VPP node.
        :param node_vxlan_if: VPP node interface key to create VXLAN tunnel
            interfaces.
        :param node_vlan_if: VPP node interface key to create VLAN
            sub-interface.
        :param vxlan_count: Number of tunnel interfaces to create.
        :param vni_start: VNI start ID.
        :param src_ip_start: VXLAN tunnel source IP address start.
        :param dst_ip_start: VXLAN tunnel destination IP address start.
        :param ip_step: IP address incremental step.
        :type node: dict
        :type node_vxlan_if: str
        :type node_vlan_if: str
        :type vxlan_count: int
        :type vni_start: int
        :type src_ip_start: str
        :type dst_ip_start: str
        :type ip_step: int
        :returns: Number of created VXLAN interfaces.
        :rtype: int
        """
        src_ip_start = ip_address(src_ip_start)
        dst_ip_start = ip_address(dst_ip_start)

        if vxlan_count > 10:
            commands = list()
            for i in range(0, vxlan_count):
                try:
                    src_ip = src_ip_start + i * ip_step
                    dst_ip = dst_ip_start + i * ip_step
                except AddressValueError:
                    logger.warn(
                        u"Can't do more iterations - IP address limit "
                        u"has been reached."
                    )
                    vxlan_count = i
                    break
                commands.append(
                    f"sw_interface_add_del_address sw_if_index "
                    f"{Topology.get_interface_sw_index(node, node_vxlan_if)} "
                    f"{src_ip}/{128 if src_ip.version == 6 else 32}\n"
                )
                commands.append(
                    f"vxlan_add_del_tunnel src {src_ip} dst {dst_ip} "
                    f"vni {vni_start + i}\n"
                )
                commands.append(
                    f"create_vlan_subif sw_if_index "
                    f"{Topology.get_interface_sw_index(node, node_vlan_if)} "
                    f"vlan {i + 1}\n"
                )
            VatExecutor().write_and_execute_script(
                node, u"/tmp/create_vxlan_interfaces.config", commands
            )
            return vxlan_count

        cmd1 = u"sw_interface_add_del_address"
        args1 = dict(
            sw_if_index=InterfaceUtil.get_interface_index(node, node_vxlan_if),
            is_add=True,
            del_all=False,
            prefix=None
        )
        cmd2 = u"vxlan_add_del_tunnel_v3"
        args2 = dict(
            is_add=True,
            instance=Constants.BITWISE_NON_ZERO,
            src_address=None,
            dst_address=None,
            mcast_sw_if_index=Constants.BITWISE_NON_ZERO,
            encap_vrf_id=0,
            decap_next_index=Constants.BITWISE_NON_ZERO,
            vni=None
        )
        cmd3 = u"create_vlan_subif"
        args3 = dict(
            sw_if_index=InterfaceUtil.get_interface_index(
                node, node_vlan_if),
            vlan_id=None
        )

        with PapiSocketExecutor(node) as papi_exec:
            for i in range(0, vxlan_count):
                try:
                    src_ip = src_ip_start + i * ip_step
                    dst_ip = dst_ip_start + i * ip_step
                except AddressValueError:
                    logger.warn(
                        u"Can't do more iterations - IP address limit "
                        u"has been reached."
                    )
                    vxlan_count = i
                    break
                args1[u"prefix"] = IPUtil.create_prefix_object(
                    src_ip, 128 if src_ip_start.version == 6 else 32
                )
                args2[u"src_address"] = IPAddress.create_ip_address_object(
                    src_ip
                )
                args2[u"dst_address"] = IPAddress.create_ip_address_object(
                    dst_ip
                )
                args2[u"vni"] = int(vni_start) + i
                args3[u"vlan_id"] = i + 1
                history = bool(not 1 < i < vxlan_count - 1)
                papi_exec.add(cmd1, history=history, **args1).\
                    add(cmd2, history=history, **args2).\
                    add(cmd3, history=history, **args3)
            papi_exec.get_replies()

        return vxlan_count
Beispiel #24
0
    def vpp_create_vxlan_and_vlan_interfaces(node, node_vxlan_if, node_vlan_if,
                                             vxlan_count, vni_start,
                                             src_ip_start, dst_ip_start,
                                             ip_step):
        """
        Configure IPs, create VXLAN interfaces and VLAN sub-interfaces on VPP
        node.

        :param node: VPP node.
        :param node_vxlan_if: VPP node interface key to create VXLAN tunnel
            interfaces.
        :param node_vlan_if: VPP node interface key to create VLAN
            sub-interface.
        :param vxlan_count: Number of tunnel interfaces to create.
        :param vni_start: VNI start ID.
        :param src_ip_start: VXLAN tunnel source IP address start.
        :param dst_ip_start: VXLAN tunnel destination IP address start.
        :param ip_step: IP address incremental step.
        :type node: dict
        :type node_vxlan_if: str
        :type node_vlan_if: str
        :type vxlan_count: int
        :type vni_start: int
        :type src_ip_start: str
        :type dst_ip_start: str
        :type ip_step: int
        :returns: Number of created VXLAN interfaces.
        :rtype: int
        """
        src_ip_addr_start = ip_address(unicode(src_ip_start))
        dst_ip_addr_start = ip_address(unicode(dst_ip_start))

        if vxlan_count > 10:
            commands = list()
            tmp_fn = '/tmp/create_vxlan_interfaces.config'
            for i in xrange(0, vxlan_count):
                try:
                    src_ip = src_ip_addr_start + i * ip_step
                    dst_ip = dst_ip_addr_start + i * ip_step
                except AddressValueError:
                    logger.warn("Can't do more iterations - IP address limit "
                                "has been reached.")
                    vxlan_count = i
                    break
                commands.append(
                    'sw_interface_add_del_address sw_if_index {sw_idx} '
                    '{ip}/{ip_len}\n'.format(
                        sw_idx=Topology.get_interface_sw_index(
                            node, node_vxlan_if),
                        ip=src_ip,
                        ip_len=128 if src_ip.version == 6 else 32))
                commands.append(
                    'vxlan_add_del_tunnel src {srcip} dst {dstip} vni {vni}\n'\
                        .format(srcip=src_ip, dstip=dst_ip,
                                vni=vni_start + i))
                commands.append(
                    'create_vlan_subif sw_if_index {sw_idx} vlan {vlan}\n'\
                        .format(sw_idx=Topology.get_interface_sw_index(
                            node, node_vlan_if), vlan=i + 1))
            VatExecutor().write_and_execute_script(node, tmp_fn, commands)
            return vxlan_count

        cmd1 = 'sw_interface_add_del_address'
        args1 = dict(
            sw_if_index=InterfaceUtil.get_interface_index(node, node_vxlan_if),
            is_add=1,
            is_ipv6=1 if src_ip_addr_start.version == 6 else 0,
            del_all=0,
            address_length=128 if src_ip_addr_start.version == 6 else 32,
            address=None)
        cmd2 = 'vxlan_add_del_tunnel'
        args2 = dict(is_add=1,
                     is_ipv6=0,
                     instance=Constants.BITWISE_NON_ZERO,
                     src_address=None,
                     dst_address=None,
                     mcast_sw_if_index=Constants.BITWISE_NON_ZERO,
                     encap_vrf_id=0,
                     decap_next_index=Constants.BITWISE_NON_ZERO,
                     vni=None)
        cmd3 = 'create_vlan_subif'
        args3 = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, node_vlan_if),
                     vlan_id=None)
        err_msg = 'Failed to create VXLAN and VLAN interfaces on host {host}'.\
            format(host=node['host'])

        with PapiExecutor(node) as papi_exec:
            for i in xrange(0, vxlan_count):
                try:
                    src_ip = src_ip_addr_start + i * ip_step
                    dst_ip = dst_ip_addr_start + i * ip_step
                except AddressValueError:
                    logger.warn("Can't do more iterations - IP address limit "
                                "has been reached.")
                    vxlan_count = i
                    break
                args1['address'] = src_ip.packed
                args2['src_address'] = src_ip.packed
                args2['dst_address'] = dst_ip.packed
                args2['vni'] = int(vni_start) + i
                args3['vlan_id'] = i + 1
                history = False if 1 < i < vxlan_count else True
                papi_exec.add(cmd1, history=history, **args1).\
                    add(cmd2, history=history, **args2).\
                    add(cmd3, history=history, **args3)
                if i > 0 and i % (Constants.PAPI_MAX_API_BULK / 3) == 0:
                    papi_exec.get_replies(err_msg)
            papi_exec.get_replies()

        return vxlan_count
Beispiel #25
0
    def vpp_route_add(node, network, prefix_len, **kwargs):
        """Add route to the VPP node.

        :param node: VPP node.
        :param network: Route destination network address.
        :param prefix_len: Route destination network prefix length.
        :param kwargs: Optional key-value arguments:

            gateway: Route gateway address. (str)
            interface: Route interface. (str)
            vrf: VRF table ID. (int)
            count: number of IP addresses to add starting from network IP (int)
            local: The route is local with same prefix (increment is 1).
                If None, then is not used. (bool)
            lookup_vrf: VRF table ID for lookup. (int)
            multipath: Enable multipath routing. (bool)
            weight: Weight value for unequal cost multipath routing. (int)

        :type node: dict
        :type network: str
        :type prefix_len: int
        :type kwargs: dict
        """
        count = kwargs.get("count", 1)

        if count > 100:
            gateway = kwargs.get("gateway", '')
            interface = kwargs.get("interface", '')
            vrf = kwargs.get("vrf", None)
            multipath = kwargs.get("multipath", False)

            with VatTerminal(node, json_param=False) as vat:
                vat.vat_terminal_exec_cmd_from_template(
                    'vpp_route_add.vat',
                    network=network,
                    prefix_length=prefix_len,
                    via='via {}'.format(gateway) if gateway else '',
                    sw_if_index='sw_if_index {}'.format(
                        InterfaceUtil.get_interface_index(node, interface))
                    if interface else '',
                    vrf='vrf {}'.format(vrf) if vrf else '',
                    count='count {}'.format(count) if count else '',
                    multipath='multipath' if multipath else '')
            return

        net_addr = ip_address(unicode(network))
        cmd = 'ip_route_add_del'
        route = IPUtil.compose_vpp_route_structure(node, network, prefix_len,
                                                   **kwargs)
        args = dict(is_add=1,
                    is_multipath=int(kwargs.get('multipath', False)),
                    route=route)

        err_msg = 'Failed to add route(s) on host {host}'.format(
            host=node['host'])
        with PapiExecutor(node) as papi_exec:
            for i in xrange(kwargs.get('count', 1)):
                args['route']['prefix']['address']['un'] = \
                    IPUtil.union_addr(net_addr + i)
                history = False if 1 < i < kwargs.get('count', 1) else True
                papi_exec.add(cmd, history=history, **args)
                if i > 0 and i % Constants.PAPI_MAX_API_BULK == 0:
                    papi_exec.get_replies(err_msg)
            papi_exec.get_replies(err_msg)
Beispiel #26
0
    def configure_sr_localsid(node,
                              local_sid,
                              behavior,
                              interface=None,
                              next_hop=None,
                              fib_table=None,
                              out_if=None,
                              in_if=None,
                              src_addr=None,
                              sid_list=None):
        """Create SRv6 LocalSID and binds it to a particular behaviour on
        the given node.

        :param node: Given node to create localSID on.
        :param local_sid: LocalSID IPv6 address.
        :param behavior: SRv6 LocalSID function.
        :param interface: Interface name (Optional, required for
            L2/L3 xconnects).
        :param next_hop: Next hop IPv4/IPv6 address (Optional, required for L3
            xconnects).
        :param fib_table: FIB table for IPv4/IPv6 lookup (Optional, required for
            L3 routing).
        :param out_if: Interface name of local interface for sending traffic
            towards the Service Function (Optional, required for SRv6 endpoint
            to SR-unaware appliance).
        :param in_if: Interface name of local interface receiving the traffic
            coming back from the Service Function (Optional, required for SRv6
            endpoint to SR-unaware appliance).
        :param src_addr: Source address on the packets coming back on in_if
            interface (Optional, required for SRv6 endpoint to SR-unaware
            appliance via static proxy).
        :param sid_list: SID list (Optional, required for SRv6 endpoint to
            SR-unaware appliance via static proxy).
        :type node: dict
        :type local_sid: str
        :type behavior: str
        :type interface: str
        :type next_hop: str
        :type fib_table: str
        :type out_if: str
        :type in_if: str
        :type src_addr: str
        :type sid_list: list
        :raises ValueError: If required parameter is missing.
        """
        beh = behavior.replace(u".", u"_").upper()
        # There is no SRv6Behaviour enum defined for functions from SRv6 plugins
        # so we need to use CLI command to configure it.
        if beh in (getattr(SRv6Behavior, u"END_AD").name,
                   getattr(SRv6Behavior,
                           u"END_AS").name, getattr(SRv6Behavior,
                                                    u"END_AM").name):
            if beh == getattr(SRv6Behavior, u"END_AS").name:
                if next_hop is None or out_if is None or in_if is None or \
                        src_addr is None or sid_list is None:
                    raise ValueError(f"Required parameter(s) missing.\n"
                                     f"next_hop:{next_hop}\n "
                                     f"out_if:{out_if}\n"
                                     f"in_if:{in_if}\n"
                                     f"src_addr:{src_addr}\n"
                                     f"sid_list:{sid_list}")
                sid_conf = f"next {u' next '.join(sid_list)}"
                params = f"nh {next_hop} oif {out_if} iif {in_if} " \
                    f"src {src_addr} {sid_conf}"
            else:
                if next_hop is None or out_if is None or in_if is None:
                    raise ValueError(f"Required parameter(s) missing.\n"
                                     f"next_hop:{next_hop}\n"
                                     f"out_if:{out_if}\n"
                                     f"in_if:{in_if}")
                params = f"nh {next_hop} oif {out_if} iif {in_if}"

            cli_cmd = f"sr localsid address {local_sid} behavior {behavior} " \
                f"{params}"

            PapiSocketExecutor.run_cli_cmd(node, cli_cmd)
            return

        cmd = u"sr_localsid_add_del"
        args = dict(is_del=False,
                    localsid=IPv6Address(local_sid).packed,
                    end_psp=False,
                    behavior=getattr(SRv6Behavior, beh).value,
                    sw_if_index=Constants.BITWISE_NON_ZERO,
                    vlan_index=0,
                    fib_table=0,
                    nh_addr=0)
        err_msg = f"Failed to add SR localSID {local_sid} " \
            f"host {node[u'host']}"
        if beh in (getattr(SRv6Behavior, u"END_X").name,
                   getattr(SRv6Behavior,
                           u"END_DX4").name, getattr(SRv6Behavior,
                                                     u"END_DX6").name):
            if interface is None or next_hop is None:
                raise ValueError(f"Required parameter(s) missing.\n"
                                 f"interface:{interface}\n"
                                 f"next_hop:{next_hop}")
            args[u"sw_if_index"] = InterfaceUtil.get_interface_index(
                node, interface)
            args[u"nh_addr"] = IPAddress.create_ip_address_object(
                ip_address(next_hop))
        elif beh == getattr(SRv6Behavior, u"END_DX2").name:
            if interface is None:
                raise ValueError(
                    f"Required parameter missing.\ninterface: {interface}")
            args[u"sw_if_index"] = InterfaceUtil.get_interface_index(
                node, interface)
        elif beh in (getattr(SRv6Behavior,
                             u"END_DT4").name, getattr(SRv6Behavior,
                                                       u"END_DT6").name):
            if fib_table is None:
                raise ValueError(f"Required parameter missing.\n"
                                 f"fib_table: {fib_table}")
            args[u"fib_table"] = fib_table

        with PapiSocketExecutor(node) as papi_exec:
            papi_exec.add(cmd, **args).get_reply(err_msg)
Beispiel #27
0
    def vpp_route_add(node, network, prefix_len, strict=True, **kwargs):
        """Add route to the VPP node. Prefer multipath behavior.

        :param node: VPP node.
        :param network: Route destination network address.
        :param prefix_len: Route destination network prefix length.
        :param strict: If true, fail if address has host bits set.
        :param kwargs: Optional key-value arguments:

            gateway: Route gateway address. (str)
            interface: Route interface. (str)
            vrf: VRF table ID. (int)
            count: number of IP addresses to add starting from network IP (int)
            local: The route is local with same prefix (increment is 1 network)
            If None, then is not used. (bool)
            lookup_vrf: VRF table ID for lookup. (int)
            multipath: Enable multipath routing. (bool) Default: True.
            weight: Weight value for unequal cost multipath routing. (int)

        :type node: dict
        :type network: str
        :type prefix_len: int
        :type strict: bool
        :type kwargs: dict
        :raises RuntimeError: If the argument combination is not supported.
        """
        count = kwargs.get(u"count", 1)

        if count > 100:
            if not kwargs.get(u"multipath", True):
                raise RuntimeError(
                    u"VAT exec supports only multipath behavior")
            gateway = kwargs.get(u"gateway", u"")
            interface = kwargs.get(u"interface", u"")
            local = kwargs.get(u"local", u"")
            if interface:
                interface = InterfaceUtil.vpp_get_interface_name(
                    node, InterfaceUtil.get_interface_index(node, interface))
            vrf = kwargs.get(u"vrf", None)
            trailers = list()
            if vrf:
                trailers.append(f"table {vrf}")
            if gateway:
                trailers.append(f"via {gateway}")
                if interface:
                    trailers.append(interface)
            elif interface:
                trailers.append(f"via {interface}")
            if local:
                if gateway or interface:
                    raise RuntimeError(u"Unsupported combination with local.")
                trailers.append(u"local")
            trailer = u" ".join(trailers)
            command_parts = [u"exec ip route add", u"network goes here"]
            if trailer:
                command_parts.append(trailer)
            netiter = NetworkIncrement(ip_network(f"{network}/{prefix_len}",
                                                  strict=strict),
                                       format=u"slash")
            tmp_filename = u"/tmp/routes.config"
            with open(tmp_filename, u"w") as tmp_file:
                for _ in range(count):
                    command_parts[1] = netiter.inc_fmt()
                    print(u" ".join(command_parts), file=tmp_file)
            VatExecutor().execute_script(tmp_filename,
                                         node,
                                         timeout=1800,
                                         json_out=False,
                                         copy_on_execute=True,
                                         history=False)
            os.remove(tmp_filename)
            return

        cmd = u"ip_route_add_del"
        args = dict(is_add=True,
                    is_multipath=kwargs.get(u"multipath", True),
                    route=None)
        err_msg = f"Failed to add route(s) on host {node[u'host']}"

        netiter = NetworkIncrement(ip_network(f"{network}/{prefix_len}",
                                              strict=strict),
                                   format=u"addr")
        with PapiSocketExecutor(node) as papi_exec:
            for i in range(count):
                args[u"route"] = IPUtil.compose_vpp_route_structure(
                    node, netiter.inc_fmt(), prefix_len, **kwargs)
                history = bool(not 0 < i < count - 1)
                papi_exec.add(cmd, history=history, **args)
            papi_exec.get_replies(err_msg)
Beispiel #28
0
    def compose_vpp_route_structure(node, network, prefix_len, **kwargs):
        """Create route object for ip_route_add_del api call.

        :param node: VPP node.
        :param network: Route destination network address.
        :param prefix_len: Route destination network prefix length.
        :param kwargs: Optional key-value arguments:

            gateway: Route gateway address. (str)
            interface: Route interface. (str)
            vrf: VRF table ID. (int)
            count: number of IP addresses to add starting from network IP (int)
            local: The route is local with same prefix (increment is 1).
                If None, then is not used. (bool)
            lookup_vrf: VRF table ID for lookup. (int)
            multipath: Enable multipath routing. (bool)
            weight: Weight value for unequal cost multipath routing. (int)

        :type node: dict
        :type network: str
        :type prefix_len: int
        :type kwargs: dict
        :returns: route parameter basic structure
        :rtype: dict
        """
        interface = kwargs.get(u"interface", u"")
        gateway = kwargs.get(u"gateway", u"")

        net_addr = ip_address(network)

        prefix = IPUtil.create_prefix_object(net_addr, prefix_len)

        paths = list()
        n_hop = dict(address=IPAddress.union_addr(ip_address(gateway))
                     if gateway else 0,
                     via_label=MPLS_LABEL_INVALID,
                     obj_id=Constants.BITWISE_NON_ZERO)
        path = dict(sw_if_index=InterfaceUtil.get_interface_index(
            node, interface) if interface else Constants.BITWISE_NON_ZERO,
                    table_id=int(kwargs.get(u"lookup_vrf", 0)),
                    rpf_id=Constants.BITWISE_NON_ZERO,
                    weight=int(kwargs.get(u"weight", 1)),
                    preference=1,
                    type=getattr(
                        FibPathType,
                        u"FIB_PATH_TYPE_LOCAL" if kwargs.get(u"local", False)
                        else u"FIB_PATH_TYPE_NORMAL").value,
                    flags=getattr(FibPathFlags, u"FIB_PATH_FLAG_NONE").value,
                    proto=getattr(
                        FibPathNhProto,
                        u"FIB_PATH_NH_PROTO_IP6" if net_addr.version == 6 else
                        u"FIB_PATH_NH_PROTO_IP4").value,
                    nh=n_hop,
                    n_labels=0,
                    label_stack=list(0 for _ in range(16)))
        paths.append(path)

        route = dict(table_id=int(kwargs.get(u"vrf", 0)),
                     prefix=prefix,
                     n_paths=len(paths),
                     paths=paths)
        return route