Exemple #1
0
    def get_adj_mac(nodes_info, dut_node, dut_if1, dut_if2):
        """
        Get adjacency MAC addresses of the DUT node.

        :param nodes_info: All the nodes info in the topology file.
        :param dut_node: Will execute the l3fwd on this node
        :param dut_if1: The test link interface 1.
        :param dut_if2: The test link interface 2.
        :type nodes_info: dict
        :type dut_node: dict
        :type dut_if1: str
        :type dut_if2: str
        :returns: Returns MAC addresses of adjacency DUT nodes.
        :rtype: str
        """
        if_key0 = dut_if1
        if_key1 = dut_if2
        if_pci0 = Topology.get_interface_pci_addr(dut_node, if_key0)
        if_pci1 = Topology.get_interface_pci_addr(dut_node, if_key1)

        # detect which is the port 0
        if min(if_pci0, if_pci1) != if_pci0:
            if_key0, if_key1 = if_key1, if_key0

        adj_node0, adj_if_key0 = Topology.get_adjacent_node_and_interface( \
                                 nodes_info, dut_node, if_key0)
        adj_node1, adj_if_key1 = Topology.get_adjacent_node_and_interface( \
                                 nodes_info, dut_node, if_key1)

        adj_mac0 = Topology.get_interface_mac(adj_node0, adj_if_key0)
        adj_mac1 = Topology.get_interface_mac(adj_node1, adj_if_key1)

        return adj_mac0, adj_mac1
Exemple #2
0
    def construct_vms_on_node(self, **kwargs):
        """Construct 1..Mx1..N VMs(s) on node with specified name.

        :param kwargs: Named parameters.
        :type kwargs: dict
        """
        node = kwargs[u"node"]
        nf_chains = int(kwargs[u"nf_chains"])
        nf_nodes = int(kwargs[u"nf_nodes"])
        queues = kwargs[u"rxq_count_int"] if kwargs[u"auto_scale"] else 1
        vs_dtc = kwargs[u"vs_dtc"]
        nf_dtc = kwargs[u"nf_dtc"]
        if kwargs[u"auto_scale"] and not kwargs[u"fixed_auto_scale"]:
            nf_dtc = kwargs[u"vs_dtc"]
        nf_dtcr = kwargs[u"nf_dtcr"] \
            if isinstance(kwargs[u"nf_dtcr"], int) else 2

        for nf_chain in range(1, nf_chains + 1):
            for nf_node in range(1, nf_nodes + 1):
                qemu_id = (nf_chain - 1) * nf_nodes + nf_node
                name = f"{node}_{qemu_id}"
                idx1 = (nf_chain - 1) * nf_nodes * 2 + nf_node * 2 - 1

                vif1_mac = Topology.get_interface_mac(
                    self.nodes[node], f"vhost{idx1}"
                ) if kwargs[u"vnf"] == u"testpmd_mac" \
                    else kwargs[u"tg_pf1_mac"] if nf_node == 1 \
                    else f"52:54:00:00:{(qemu_id - 1):02x}:02"
                idx2 = (nf_chain - 1) * nf_nodes * 2 + nf_node * 2
                vif2_mac = Topology.get_interface_mac(
                    self.nodes[node], f"vhost{idx2}"
                ) if kwargs[u"vnf"] == u"testpmd_mac" \
                    else kwargs[u"tg_pf2_mac"] if nf_node == nf_nodes \
                    else f"52:54:00:00:{(qemu_id + 1):02x}:01"

                self.machines_affinity[name] = CpuUtils.get_affinity_nf(
                    nodes=self.nodes,
                    node=node,
                    nf_chains=nf_chains,
                    nf_nodes=nf_nodes,
                    nf_chain=nf_chain,
                    nf_node=nf_node,
                    vs_dtc=vs_dtc,
                    nf_dtc=nf_dtc,
                    nf_dtcr=nf_dtcr)

                try:
                    getattr(self, f'_c_{kwargs["vnf"]}')(qemu_id=qemu_id,
                                                         name=name,
                                                         queues=queues,
                                                         **kwargs)
                except AttributeError:
                    self._c_default(qemu_id=qemu_id,
                                    name=name,
                                    queues=queues,
                                    vif1_mac=vif1_mac,
                                    vif2_mac=vif2_mac,
                                    **kwargs)
Exemple #3
0
    def get_adj_mac(nodes, node, if1, if2):
        """
        Get adjacency MAC addresses of the DUT node.

        :param nodes: All the nodes info in the topology file.
        :param node: DUT node.
        :param if1: The test link interface 1.
        :param if2: The test link interface 2.
        :type nodes: dict
        :type node: dict
        :type if1: str
        :type if2: str
        :returns: Returns MAC addresses of adjacency DUT nodes and PCI
            addresses.
        :rtype: str
        """
        if_key0 = if1
        if_key1 = if2
        if_pci0 = Topology.get_interface_pci_addr(node, if_key0)
        if_pci1 = Topology.get_interface_pci_addr(node, if_key1)

        # Detect which is the port 0.
        if min(if_pci0, if_pci1) != if_pci0:
            if_key0, if_key1 = if_key1, if_key0
            L3fwdTest.patch_l3fwd(node, u"patch_l3fwd_flip_routes")

        adj_node0, adj_if_key0 = Topology.get_adjacent_node_and_interface(
            nodes, node, if_key0
        )
        adj_node1, adj_if_key1 = Topology.get_adjacent_node_and_interface(
            nodes, node, if_key1
        )
        if_pci0 = Topology.get_interface_pci_addr(node, if_key0)
        if_pci1 = Topology.get_interface_pci_addr(node, if_key1)
        adj_mac0 = Topology.get_interface_mac(adj_node0, adj_if_key0)
        adj_mac1 = Topology.get_interface_mac(adj_node1, adj_if_key1)

        return adj_mac0, adj_mac1, if_pci0, if_pci1
Exemple #4
0
    def dmm_get_interface_name(dut_node, dut_interface):
        """
        Get the interface name.

        :param dut_node: Node to get the interface name on.
        :param dut_interface: Interface key.
        :type dut_node: dict
        :type dut_interface: str
        :returns: Interface name.
        :rtype: str
        """
        mac = Topology.get_interface_mac(dut_node, dut_interface)
        cmd = 'ifconfig -a | grep {0}'.format(mac)
        (stdout, _) = exec_cmd_no_error(dut_node, cmd)
        interface_name = stdout.split(' ', 1)[0]
        return interface_name
    def setup_arp_on_all_duts(nodes_info, nodes_addr):
        """For all DUT nodes extract MAC and IP addresses of adjacent
        interfaces from topology and use them to setup ARP entries.

        :param nodes_info: Dictionary containing information on all nodes
        in topology.
        :param nodes_addr: Nodes IPv4 addresses.
        :type nodes_info: dict
        :type nodes_addr: dict
        """
        for node in nodes_info.values():
            if node['type'] == NodeType.TG:
                continue
            for iface_key in node['interfaces'].keys():
                adj_node, adj_int = Topology.\
                    get_adjacent_node_and_interface(nodes_info, node, iface_key)
                ip_address = IPv4Setup.get_ip_addr(adj_node, adj_int,
                                                   nodes_addr)
                mac_address = Topology.get_interface_mac(adj_node, adj_int)
                get_node(node).set_arp(iface_key, ip_address, mac_address)
Exemple #6
0
    def vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain(
            node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start,
            ip_step, bd_id_start):
        """
        Configure ARPs and routes for VXLAN interfaces and put each pair of
        VXLAN tunnel interface and VLAN sub-interface to separate bridge-domain.

        :param node: VPP node.
        :param node_vxlan_if: VPP node interface key where VXLAN tunnel
            interfaces have been created.
        :param vxlan_count: Number of tunnel interfaces.
        :param op_node: Opposite VPP node for VXLAN tunnel interfaces.
        :param op_node_if: Opposite VPP node interface key for VXLAN tunnel
            interfaces.
        :param dst_ip_start: VXLAN tunnel destination IP address start.
        :param ip_step: IP address incremental step.
        :param bd_id_start: Bridge-domain ID start.
        :type node: dict
        :type node_vxlan_if: str
        :type vxlan_count: int
        :type op_node: dict
        :type op_node_if:
        :type dst_ip_start: str
        :type ip_step: int
        :type bd_id_start: int
        """
        dst_ip_start = ip_address(dst_ip_start)

        if vxlan_count > 1:
            idx_vxlan_if = Topology.get_interface_sw_index(node, node_vxlan_if)
            commands = list()
            for i in range(0, vxlan_count):
                dst_ip = dst_ip_start + i * ip_step
                commands.append(
                    f"exec ip neighbor "
                    f"{Topology.get_interface_name(node, node_vxlan_if)} "
                    f"{dst_ip} "
                    f"{Topology.get_interface_mac(op_node, op_node_if)} static "
                    f"\n"
                )
                commands.append(
                    f"ip_route_add_del "
                    f"{dst_ip}/{128 if dst_ip.version == 6 else 32} count 1 "
                    f"via {dst_ip} sw_if_index {idx_vxlan_if}\n"
                )
                sw_idx_vxlan = Topology.get_interface_sw_index(
                    node, f"vxlan_tunnel{i + 1}"
                )
                commands.append(
                    f"sw_interface_set_l2_bridge sw_if_index {sw_idx_vxlan} "
                    f"bd_id {bd_id_start + i} shg 0 enable\n"
                )
                sw_idx_vlan = Topology.get_interface_sw_index(
                    node, f"vlan_subif{i + 1}"
                )
                commands.append(
                    f"sw_interface_set_l2_bridge sw_if_index {sw_idx_vlan} "
                    f"bd_id {bd_id_start + i} shg 0 enable\n"
                )
            VatExecutor().write_and_execute_script(
                node, u"/tmp/configure_routes_and_bridge_domains.config",
                commands
            )
            return

        cmd1 = u"ip_neighbor_add_del"
        neighbor = dict(
            sw_if_index=Topology.get_interface_sw_index(node, node_vxlan_if),
            flags=0,
            mac_address=Topology.get_interface_mac(op_node, op_node_if),
            ip_address=u""
        )
        args1 = dict(
            is_add=1,
            neighbor=neighbor
        )
        cmd2 = u"ip_route_add_del"
        kwargs = dict(
            interface=node_vxlan_if,
            gateway=str(dst_ip_start)
        )
        route = IPUtil.compose_vpp_route_structure(
            node, str(dst_ip_start),
            128 if dst_ip_start.version == 6 else 32, **kwargs
        )
        args2 = dict(
            is_add=1,
            is_multipath=0,
            route=route
        )
        cmd3 = u"sw_interface_set_l2_bridge"
        args3 = dict(
            rx_sw_if_index=None,
            bd_id=None,
            shg=0,
            port_type=0,
            enable=1
        )
        args4 = dict(
            rx_sw_if_index=None,
            bd_id=None,
            shg=0,
            port_type=0,
            enable=1
        )

        with PapiSocketExecutor(node) as papi_exec:
            for i in range(0, vxlan_count):
                args1[u"neighbor"][u"ip_address"] = \
                    str(dst_ip_start + i * ip_step)
                args2[u"route"][u"prefix"][u"address"][u"un"] = \
                    IPAddress.union_addr(dst_ip_start + i * ip_step)
                args2[u"route"][u"paths"][0][u"nh"][u"address"] = \
                    IPAddress.union_addr(dst_ip_start + i * ip_step)
                args3[u"rx_sw_if_index"] = Topology.get_interface_sw_index(
                    node, f"vxlan_tunnel{i+1}"
                )
                args3[u"bd_id"] = int(bd_id_start+i)
                args4[u"rx_sw_if_index"] = Topology.get_interface_sw_index(
                    node, f"vlan_subif{i+1}"
                )
                args4[u"bd_id"] = int(bd_id_start+i)
                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). \
                    add(cmd3, history=history, **args4)
            papi_exec.get_replies()
Exemple #7
0
    def initialize_traffic_generator(self,
                                     tg_node,
                                     tg_if1,
                                     tg_if2,
                                     tg_if1_adj_node,
                                     tg_if1_adj_if,
                                     tg_if2_adj_node,
                                     tg_if2_adj_if,
                                     test_type,
                                     tg_if1_dst_mac=None,
                                     tg_if2_dst_mac=None):
        """TG initialization.

        :param tg_node: Traffic generator node.
        :param tg_if1: TG - name of first interface.
        :param tg_if2: TG - name of second interface.
        :param tg_if1_adj_node: TG if1 adjecent node.
        :param tg_if1_adj_if: TG if1 adjecent interface.
        :param tg_if2_adj_node: TG if2 adjecent node.
        :param tg_if2_adj_if: TG if2 adjecent interface.
        :param test_type: 'L2' or 'L3' - src/dst MAC address.
        :param tg_if1_dst_mac: Interface 1 destination MAC address.
        :param tg_if2_dst_mac: Interface 2 destination MAC address.
        :type tg_node: dict
        :type tg_if1: str
        :type tg_if2: str
        :type tg_if1_adj_node: dict
        :type tg_if1_adj_if: str
        :type tg_if2_adj_node: dict
        :type tg_if2_adj_if: str
        :type test_type: str
        :type tg_if1_dst_mac: str
        :type tg_if2_dst_mac: str
        :returns: nothing
        :raises: RuntimeError in case of issue during initialization.
        """

        topo = Topology()

        if tg_node['type'] != NodeType.TG:
            raise RuntimeError('Node type is not a TG')
        self._node = tg_node

        if tg_node['subtype'] == NodeSubTypeTG.TREX:
            trex_path = "/opt/trex-core-2.25"

            ssh = SSH()
            ssh.connect(tg_node)

            (ret, stdout, stderr) = ssh.exec_command(
                "sudo -E sh -c '{}/resources/tools/t-rex/"
                "t-rex-installer.sh'".format(Constants.REMOTE_FW_DIR),
                timeout=1800)
            if int(ret) != 0:
                logger.error('trex installation failed: {0}'.format(stdout +
                                                                    stderr))
                raise RuntimeError('Installation of TG failed')

            if1_pci = topo.get_interface_pci_addr(tg_node, tg_if1)
            if2_pci = topo.get_interface_pci_addr(tg_node, tg_if2)
            if1_mac = topo.get_interface_mac(tg_node, tg_if1)
            if2_mac = topo.get_interface_mac(tg_node, tg_if2)

            if test_type == 'L2':
                if1_adj_mac = if2_mac
                if2_adj_mac = if1_mac
            elif test_type == 'L3':
                if1_adj_mac = topo.get_interface_mac(tg_if1_adj_node,
                                                     tg_if1_adj_if)
                if2_adj_mac = topo.get_interface_mac(tg_if2_adj_node,
                                                     tg_if2_adj_if)
            else:
                raise ValueError("test_type unknown")

            if tg_if1_dst_mac is not None and tg_if2_dst_mac is not None:
                if1_adj_mac = tg_if1_dst_mac
                if2_adj_mac = tg_if2_dst_mac

            if min(if1_pci, if2_pci) != if1_pci:
                if1_mac, if2_mac = if2_mac, if1_mac
                if1_pci, if2_pci = if2_pci, if1_pci
                if1_adj_mac, if2_adj_mac = if2_adj_mac, if1_adj_mac
                self._ifaces_reordered = True

            if1_mac_hex = "0x" + if1_mac.replace(":", ",0x")
            if2_mac_hex = "0x" + if2_mac.replace(":", ",0x")
            if1_adj_mac_hex = "0x" + if1_adj_mac.replace(":", ",0x")
            if2_adj_mac_hex = "0x" + if2_adj_mac.replace(":", ",0x")

            (ret, stdout, stderr) = ssh.exec_command(
                "sudo sh -c 'cat << EOF > /etc/trex_cfg.yaml\n"
                "- port_limit      : 2\n"
                "  version         : 2\n"
                "  interfaces      : [\"{}\",\"{}\"]\n"
                "  port_info       :\n"
                "          - dest_mac        :   [{}]\n"
                "            src_mac         :   [{}]\n"
                "          - dest_mac        :   [{}]\n"
                "            src_mac         :   [{}]\n"
                "EOF'"\
                .format(if1_pci, if2_pci,
                        if1_adj_mac_hex, if1_mac_hex,
                        if2_adj_mac_hex, if2_mac_hex))
            if int(ret) != 0:
                logger.error("failed to create t-rex config: {}"\
                .format(stdout + stderr))
                raise RuntimeError('trex config generation error')

            max_startup_retries = 3
            while max_startup_retries > 0:
                # kill T-rex only if it is already running
                (ret, _, _) = ssh.exec_command(
                    "sh -c 'pgrep t-rex && sudo pkill t-rex && sleep 3'")

                # configure T-rex
                (ret, stdout, stderr) = ssh.exec_command(
                    "sh -c 'cd {0}/scripts/ && sudo ./trex-cfg'"\
                    .format(trex_path))
                if int(ret) != 0:
                    logger.error('trex-cfg failed: {0}'.format(stdout +
                                                               stderr))
                    raise RuntimeError('trex-cfg failed')

                # start T-rex
                (ret, _, _) = ssh.exec_command(
                    "sh -c 'cd {0}/scripts/ && "
                    "sudo nohup ./t-rex-64 -i -c 7 --iom 0 > /dev/null 2>&1 &'"
                    "> /dev/null"\
                    .format(trex_path))
                if int(ret) != 0:
                    raise RuntimeError('t-rex-64 startup failed')

                # get T-rex server info
                (ret, _, _) = ssh.exec_command(
                    "sh -c 'sleep 3; "
                    "{0}/resources/tools/t-rex/t-rex-server-info.py'"\
                    .format(Constants.REMOTE_FW_DIR),
                    timeout=120)
                if int(ret) == 0:
                    # If we get info T-rex is running
                    return
                # try again
                max_startup_retries -= 1
            # after max retries T-rex is still not responding to API
            # critical error occurred
            raise RuntimeError('t-rex-64 startup failed')
    def start_the_l3fwd_test(nodes_info, dut_node, dut_if1, dut_if2, nb_cores,
                             lcores_list, queue_nums, jumbo_frames):
        """
        Execute the l3fwd on the dut_node.

        :param nodes_info: All the nodes info in the topology file.
        :param dut_node: Will execute the l3fwd on this node
        :param dut_if1: The test link interface 1.
        :param dut_if2: The test link interface 2.
        :param nb_cores: The cores number for the forwarding
        :param lcores_list: The lcore list string for the l3fwd routing
        :param queue_nums: The queues number for the NIC
        :param jumbo_frames: Is jumbo frames or not. Accepted: yes / no
        :type nodes_info: dict
        :type dut_node: dict
        :type dut_if1: str
        :type dut_if2: str
        :type nb_cores: str
        :type lcores_list: str
        :type queue_nums: str
        :type jumbo_frames: str
        :return: none
        """

        if_key0 = dut_if1
        if_key1 = dut_if2
        if_pci0 = Topology.get_interface_pci_addr(dut_node, if_key0)
        if_pci1 = Topology.get_interface_pci_addr(dut_node, if_key1)

        # detect which is the port 0
        if min(if_pci0, if_pci1) != if_pci0:
            if_key0, if_key1 = if_key1, if_key0
            if_pci0, if_pci1 = if_pci1, if_pci0

        adj_node0, adj_if_key0 = Topology.get_adjacent_node_and_interface( \
                                 nodes_info, dut_node, if_key0)
        adj_node1, adj_if_key1 = Topology.get_adjacent_node_and_interface( \
                                 nodes_info, dut_node, if_key1)

        adj_mac0 = Topology.get_interface_mac(adj_node0, adj_if_key0)
        adj_mac1 = Topology.get_interface_mac(adj_node1, adj_if_key1)

        list_cores = lcores_list.split(',')

        # prepare the port config param
        index = 0
        port_config = ''
        for port in range(0, 2):
            for queue in range(0, int(queue_nums)):
                if int(nb_cores) == 1:
                    index = 0
                    temp_str = '({0}, {1}, {2}),'.format(port, queue, \
                                                    int(list_cores[index]))
                else:
                    temp_str = '({0}, {1}, {2}),'.format(port, queue, \
                                                    int(list_cores[index]))

                port_config += temp_str
                index = index + 1

        port_config_param = port_config.rstrip(',')

        ssh = SSH()
        ssh.connect(dut_node)

        cmd = 'cd {0}/tests/dpdk/dpdk_scripts/ && ./run_l3fwd.sh ' \
              '"{1}" "{2}" {3} {4} {5}'.format(con.REMOTE_FW_DIR, lcores_list, \
              port_config_param, adj_mac0, adj_mac1, jumbo_frames)

        (ret_code, _, stderr) = ssh.exec_command(cmd, timeout=600)
        if ret_code != 0:
            logger.error('Execute the l3fwd error: {0}'.format(stderr))
            raise Exception('Failed to execute l3fwd test at node {0}'.format(
                dut_node['host']))
Exemple #9
0
    def construct_vms_on_node(self, **kwargs):
        """Construct 1..Mx1..N VMs(s) on node with specified name.

        :param kwargs: Named parameters.
        :type kwargs: dict
        """
        node = kwargs[u"node"]
        nf_chains = int(kwargs[u"nf_chains"])
        nf_nodes = int(kwargs[u"nf_nodes"])
        queues = kwargs[u"rxq_count_int"] if kwargs[u"auto_scale"] else 1
        vs_dtc = kwargs[u"vs_dtc"]
        nf_dtc = kwargs[u"vs_dtc"] if kwargs[u"auto_scale"] \
            else kwargs[u"nf_dtc"]
        nf_dtcr = kwargs[u"nf_dtcr"] \
            if isinstance(kwargs[u"nf_dtcr"], int) else 2

        img = Constants.QEMU_VM_KERNEL

        for nf_chain in range(1, nf_chains + 1):
            for nf_node in range(1, nf_nodes + 1):
                qemu_id = (nf_chain - 1) * nf_nodes + nf_node
                name = f"{node}_{qemu_id}"
                sock1 = f"/run/vpp/sock-{qemu_id}-1"
                sock2 = f"/run/vpp/sock-{qemu_id}-2"
                idx1 = (nf_chain - 1) * nf_nodes * 2 + nf_node * 2 - 1
                vif1_mac = Topology.get_interface_mac(
                    self.nodes[node], f"vhost{idx1}"
                ) if kwargs[u"vnf"] == u"testpmd_mac" \
                    else kwargs[u"tg_pf1_mac"] if nf_node == 1 \
                    else f"52:54:00:00:{(qemu_id - 1):02x}:02"
                idx2 = (nf_chain - 1) * nf_nodes * 2 + nf_node * 2
                vif2_mac = Topology.get_interface_mac(
                    self.nodes[node], f"vhost{idx2}"
                ) if kwargs[u"vnf"] == u"testpmd_mac" \
                    else kwargs[u"tg_pf2_mac"] if nf_node == nf_nodes \
                    else f"52:54:00:00:{(qemu_id + 1):02x}:01"

                self.machines_affinity[name] = CpuUtils.get_affinity_nf(
                    nodes=self.nodes, node=node, nf_chains=nf_chains,
                    nf_nodes=nf_nodes, nf_chain=nf_chain, nf_node=nf_node,
                    vs_dtc=vs_dtc, nf_dtc=nf_dtc, nf_dtcr=nf_dtcr
                )

                self.machines[name] = QemuUtils(
                    node=self.nodes[node], qemu_id=qemu_id,
                    smp=len(self.machines_affinity[name]), mem=4096,
                    vnf=kwargs[u"vnf"], img=img
                )
                self.machines[name].configure_kernelvm_vnf(
                    mac1=f"52:54:00:00:{qemu_id:02x}:01",
                    mac2=f"52:54:00:00:{qemu_id:02x}:02",
                    vif1_mac=vif1_mac, vif2_mac=vif2_mac, queues=queues,
                    jumbo_frames=kwargs[u"jumbo"]
                )
                self.machines[name].qemu_add_vhost_user_if(
                    sock1, jumbo_frames=kwargs[u"jumbo"], queues=queues,
                    queue_size=kwargs[u"perf_qemu_qsz"],
                    csum=kwargs[u"enable_csum"], gso=kwargs[u"enable_gso"]
                )
                self.machines[name].qemu_add_vhost_user_if(
                    sock2, jumbo_frames=kwargs[u"jumbo"], queues=queues,
                    queue_size=kwargs[u"perf_qemu_qsz"],
                    csum=kwargs[u"enable_csum"], gso=kwargs[u"enable_gso"]
                )
Exemple #10
0
    def compute_circular_topology(self, nodes, filter_list=None, nic_pfs=1):
        """Return computed circular path.

        :param nodes: Nodes to append to the path.
        :param filter_list: Filter criteria list.
        :param nic_pfs: Number of PF of NIC.
        :type nodes: dict
        :type filter_list: list of strings
        :type path_count: int
        :returns: Topology information dictionary.
        :rtype: dict
        """
        t_dict = dict()
        duts = [key for key in nodes if u"DUT" in key]
        t_dict[u"duts"] = duts
        t_dict[u"duts_count"] = len(duts)
        t_dict[u"int"] = u"pf"

        for idx in range(0, nic_pfs // 2):
            self.append_node(nodes[u"TG"])
            for dut in duts:
                self.append_node(nodes[dut], filter_list=filter_list)
        self.append_node(nodes[u"TG"])
        self.compute_path(always_same_link=False)

        n_idx = 0
        t_idx = 1
        d_idx = 0
        while True:
            interface, node = self.next_interface()
            if not interface:
                break
            if node[u"type"] == u"TG":
                n_pfx = f"TG"
                p_pfx = f"pf{t_idx}"
                i_pfx = f"if{t_idx}"
                n_idx = 0
                t_idx = t_idx + 1
            else:
                n_pfx = f"DUT{n_idx // 2 + 1}"
                p_pfx = f"pf{d_idx % 2 + t_idx - 1}"
                i_pfx = f"if{d_idx % 2 + t_idx - 1}"
                n_idx = n_idx + 1
                d_idx = d_idx + 1

            t_dict[f"{n_pfx}"] = node
            t_dict[f"{n_pfx}_{p_pfx}"] = [interface]
            t_dict[f"{n_pfx}_{p_pfx}_mac"] = \
                [Topology.get_interface_mac(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_vlan"] = \
                [Topology.get_interface_vlan(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_pci"] = \
                [Topology.get_interface_pci_addr(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_ip4_addr"] = \
                [Topology.get_interface_ip4(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_ip4_prefix"] = \
                [Topology.get_interface_ip4_prefix_length(node, interface)]
            if f"{n_pfx}_pf_pci" not in t_dict:
                t_dict[f"{n_pfx}_pf_pci"] = []
            t_dict[f"{n_pfx}_pf_pci"].append(
                Topology.get_interface_pci_addr(node, interface))
            if f"{n_pfx}_pf_keys" not in t_dict:
                t_dict[f"{n_pfx}_pf_keys"] = []
            t_dict[f"{n_pfx}_pf_keys"].append(interface)
            # Backward compatibility below
            t_dict[f"{n_pfx.lower()}_{i_pfx}"] = interface
            t_dict[f"{n_pfx.lower()}_{i_pfx}_mac"] = \
                Topology.get_interface_mac(node, interface)
            t_dict[f"{n_pfx.lower()}_{i_pfx}_pci"] = \
                Topology.get_interface_pci_addr(node, interface)
            t_dict[f"{n_pfx.lower()}_{i_pfx}_ip4_addr"] = \
                Topology.get_interface_ip4(node, interface)
            t_dict[f"{n_pfx.lower()}_{i_pfx}_ip4_prefix"] = \
                Topology.get_interface_ip4_prefix_length(node, interface)

        self.clear_path()
        return t_dict
Exemple #11
0
    def compute_circular_topology(self,
                                  nodes,
                                  filter_list=None,
                                  nic_pfs=1,
                                  always_same_link=False,
                                  topo_has_tg=True,
                                  topo_has_dut=True):
        """Return computed circular path.

        :param nodes: Nodes to append to the path.
        :param filter_list: Filter criteria list.
        :param nic_pfs: Number of PF of NIC.
        :param always_same_link: If True use always same link between two nodes
            in path. If False use different link (if available)
            between two nodes if one link was used before.
        :param topo_has_tg: If True, the topology has a TG node. If False,
            the topology consists entirely of DUT nodes.
        :param topo_has_dut: If True, the topology has a DUT node(s). If False,
            the topology consists entirely of TG nodes.
        :type nodes: dict
        :type filter_list: list of strings
        :type nic_pfs: int
        :type always_same_link: bool
        :type topo_has_tg: bool
        :type topo_has_dut: bool
        :returns: Topology information dictionary.
        :rtype: dict
        :raises RuntimeError: If unsupported combination of parameters.
        """
        t_dict = dict()
        if topo_has_dut:
            duts = [key for key in nodes if u"DUT" in key]
            t_dict[u"duts"] = duts
            t_dict[u"duts_count"] = len(duts)
            t_dict[u"int"] = u"pf"

        for _ in range(0, nic_pfs // 2):
            if topo_has_tg:
                if topo_has_dut:
                    self.append_node(nodes[u"TG"])
                else:
                    self.append_node(nodes[u"TG"], filter_list=filter_list)
            if topo_has_dut:
                for dut in duts:
                    self.append_node(nodes[dut], filter_list=filter_list)
        if topo_has_tg:
            if topo_has_dut:
                self.append_node(nodes[u"TG"])
            else:
                self.append_node(nodes[u"TG"], filter_list=filter_list)
        self.compute_path(always_same_link, topo_has_dut)

        n_idx = 0  # node index
        t_idx = 1  # TG interface index
        d_idx = 0  # DUT interface index
        prev_host = None
        while True:
            interface, node = self.next_interface()
            if not interface:
                break
            if topo_has_tg and node.get(u"type") == u"TG":
                n_pfx = f"TG"  # node prefix
                p_pfx = f"pf{t_idx}"  # physical interface prefix
                i_pfx = f"if{t_idx}"  # [backwards compatible] interface prefix
                n_idx = 0
                t_idx = t_idx + 1
            elif topo_has_tg and topo_has_dut:
                # Each node has 2 interfaces, starting with 1
                # Calculate prefixes appropriately for current
                # path topology nomenclature:
                #   tg1_if1 -> dut1_if1 -> dut1_if2 ->
                #        [dut2_if1 -> dut2_if2 ...] -> tg1_if2
                n_pfx = f"DUT{n_idx // 2 + 1}"
                p_pfx = f"pf{d_idx % 2 + t_idx - 1}"
                i_pfx = f"if{d_idx % 2 + t_idx - 1}"
                n_idx = n_idx + 1
                d_idx = d_idx + 1
            elif not topo_has_tg and always_same_link:
                this_host = node.get(u"host")
                if prev_host != this_host:
                    # When moving to a new host in the path,
                    # increment the node index (n_idx) and
                    # reset DUT interface index (d_idx) to 1.
                    n_idx = n_idx + 1
                    d_idx = 1
                n_pfx = f"DUT{n_idx}"
                p_pfx = f"pf{d_idx}"
                i_pfx = f"if{d_idx}"
                d_idx = d_idx + 1
            else:
                raise RuntimeError(u"Unsupported combination of paramters")

            t_dict[f"{n_pfx}"] = node
            t_dict[f"{n_pfx}_{p_pfx}"] = [interface]
            t_dict[f"{n_pfx}_{p_pfx}_mac"] = \
                [Topology.get_interface_mac(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_vlan"] = \
                [Topology.get_interface_vlan(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_pci"] = \
                [Topology.get_interface_pci_addr(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_ip4_addr"] = \
                [Topology.get_interface_ip4(node, interface)]
            t_dict[f"{n_pfx}_{p_pfx}_ip4_prefix"] = \
                [Topology.get_interface_ip4_prefix_length(node, interface)]
            if f"{n_pfx}_pf_pci" not in t_dict:
                t_dict[f"{n_pfx}_pf_pci"] = []
            t_dict[f"{n_pfx}_pf_pci"].append(
                Topology.get_interface_pci_addr(node, interface))
            if f"{n_pfx}_pf_keys" not in t_dict:
                t_dict[f"{n_pfx}_pf_keys"] = []
            t_dict[f"{n_pfx}_pf_keys"].append(interface)
            # Backward compatibility below
            t_dict[f"{n_pfx.lower()}_{i_pfx}"] = interface
            t_dict[f"{n_pfx.lower()}_{i_pfx}_mac"] = \
                Topology.get_interface_mac(node, interface)
            t_dict[f"{n_pfx.lower()}_{i_pfx}_pci"] = \
                Topology.get_interface_pci_addr(node, interface)
            t_dict[f"{n_pfx.lower()}_{i_pfx}_ip4_addr"] = \
                Topology.get_interface_ip4(node, interface)
            t_dict[f"{n_pfx.lower()}_{i_pfx}_ip4_prefix"] = \
                Topology.get_interface_ip4_prefix_length(node, interface)

        self.clear_path()
        return t_dict
Exemple #12
0
    def vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain(
            node, node_vxlan_if, vxlan_count, op_node, op_node_if,
            dst_ip_start, ip_step, bd_id_start):
        """
        Configure ARPs and routes for VXLAN interfaces and put each pair of
        VXLAN tunnel interface and VLAN sub-interface to separate bridge-domain.

        :param node: VPP node.
        :param node_vxlan_if: VPP node interface key where VXLAN tunnel
            interfaces have been created.
        :param vxlan_count: Number of tunnel interfaces.
        :param op_node: Opposite VPP node for VXLAN tunnel interfaces.
        :param op_node_if: Opposite VPP node interface key for VXLAN tunnel
            interfaces.
        :param dst_ip_start: VXLAN tunnel destination IP address start.
        :param ip_step: IP address incremental step.
        :param bd_id_start: Bridge-domain ID start.
        :type node: dict
        :type node_vxlan_if: str
        :type vxlan_count: int
        :type op_node: dict
        :type op_node_if:
        :type dst_ip_start: str
        :type ip_step: int
        :type bd_id_start: int
        """
        dst_ip_addr_start = ip_address(unicode(dst_ip_start))

        if vxlan_count > 1:
            sw_idx_vxlan = Topology.get_interface_sw_index(node, node_vxlan_if)
            tmp_fn = '/tmp/configure_routes_and_bridge_domains.config'
            commands = list()
            for i in xrange(0, vxlan_count):
                dst_ip = dst_ip_addr_start + i * ip_step
                commands.append(
                    'ip_neighbor_add_del sw_if_index {sw_idx} dst {ip} '
                    'mac {mac}\n'.format(sw_idx=sw_idx_vxlan,
                                         ip=dst_ip,
                                         mac=Topology.get_interface_mac(
                                             op_node, op_node_if)))
                commands.append(
                    'ip_route_add_del {ip}/{ip_len} count 1 via {ip} '
                    'sw_if_index {sw_idx}\n'.format(
                        ip=dst_ip,
                        ip_len=128 if dst_ip.version == 6 else 32,
                        sw_idx=sw_idx_vxlan))
                commands.append(
                    'sw_interface_set_l2_bridge sw_if_index {sw_idx} '
                    'bd_id {bd_id} shg 0 enable\n'.format(
                        sw_idx=Topology.get_interface_sw_index(
                            node, 'vxlan_tunnel{nr}'.format(nr=i + 1)),
                        bd_id=bd_id_start + i))
                commands.append(
                    'sw_interface_set_l2_bridge sw_if_index {sw_idx} '
                    'bd_id {bd_id} shg 0 enable\n'.format(
                        sw_idx=Topology.get_interface_sw_index(
                            node, 'vlan_subif{nr}'.format(nr=i + 1)),
                        bd_id=bd_id_start + i))
            VatExecutor().write_and_execute_script(node, tmp_fn, commands)
            return

        cmd1 = 'ip_neighbor_add_del'
        neighbor = dict(
            sw_if_index=Topology.get_interface_sw_index(node, node_vxlan_if),
            flags=0,
            mac_address=Topology.get_interface_mac(op_node, op_node_if),
            ip_address='')
        args1 = dict(is_add=1, neighbor=neighbor)
        cmd2 = 'ip_route_add_del'
        kwargs = dict(interface=node_vxlan_if, gateway=str(dst_ip_addr_start))
        route = IPUtil.compose_vpp_route_structure(
            node, str(dst_ip_addr_start),
            128 if dst_ip_addr_start.version == 6 else 32, **kwargs)
        args2 = dict(is_add=1, is_multipath=0, route=route)
        cmd3 = 'sw_interface_set_l2_bridge'
        args3 = dict(rx_sw_if_index=None,
                     bd_id=None,
                     shg=0,
                     port_type=0,
                     enable=1)
        args4 = dict(rx_sw_if_index=None,
                     bd_id=None,
                     shg=0,
                     port_type=0,
                     enable=1)
        err_msg = 'Failed to put VXLAN and VLAN interfaces to bridge domain ' \
                  'on host {host}'.format(host=node['host'])

        with PapiExecutor(node) as papi_exec:
            for i in xrange(0, vxlan_count):
                dst_ip = dst_ip_addr_start + i * ip_step
                args1['neighbor']['ip_address'] = str(dst_ip)
                args2['route']['prefix']['address']['un'] = \
                    IPUtil.union_addr(dst_ip)
                args2['route']['paths'][0]['nh']['address'] = \
                    IPUtil.union_addr(dst_ip)
                args3['rx_sw_if_index'] = Topology.get_interface_sw_index(
                    node, 'vxlan_tunnel{nr}'.format(nr=i + 1))
                args3['bd_id'] = int(bd_id_start + i)
                args4['rx_sw_if_index'] = Topology.get_interface_sw_index(
                    node, 'vlan_subif{nr}'.format(nr=i + 1))
                args4['bd_id'] = int(bd_id_start + i)
                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). \
                    add(cmd3, history=history, **args4)
                if i > 0 and i % (Constants.PAPI_MAX_API_BULK / 4) == 0:
                    papi_exec.get_replies(err_msg)
            papi_exec.get_replies()