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
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)
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
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)
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()
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']))
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"] )
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
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
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()