X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FInterfaceUtil.py;h=3e2e38ef811e7f58ee9bc1704900b0123d5dc2bb;hb=6bcf4d40d83bbf026f9fd0105bebf579423c65a6;hp=fa6a33197c989a0497151e38cef45c773d554841;hpb=d68951ac245150eeefa6e0f4156e4c1b5c9e9325;p=csit.git diff --git a/resources/libraries/python/InterfaceUtil.py b/resources/libraries/python/InterfaceUtil.py index fa6a33197c..3e2e38ef81 100644 --- a/resources/libraries/python/InterfaceUtil.py +++ b/resources/libraries/python/InterfaceUtil.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019 Cisco and/or its affiliates. +# Copyright (c) 2020 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -103,11 +103,16 @@ class LinkBondMode(IntEnum): BOND_API_MODE_LACP = 5 +class RdmaMode(IntEnum): + """RDMA interface mode.""" + RDMA_API_MODE_AUTO = 0 + RDMA_API_MODE_IBV = 1 + RDMA_API_MODE_DV = 2 + + class InterfaceUtil: """General utilities for managing interfaces""" - __UDEV_IF_RULES_FILE = u"/etc/udev/rules.d/10-network.rules" - @staticmethod def pci_to_int(pci_str): """Convert PCI address from string format (0000:18:0a.0) to @@ -534,45 +539,6 @@ class InterfaceUtil: """ return DUTSetup.get_pci_dev_driver(node, pci_addr) - @staticmethod - def tg_set_interfaces_udev_rules(node): - """Set udev rules for interfaces. - - Create udev rules file in /etc/udev/rules.d where are rules for each - interface used by TG node, based on MAC interface has specific name. - So after unbind and bind again to kernel driver interface has same - name as before. This must be called after TG has set name for each - port in topology dictionary. - udev rule example - SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="52:54:00:e1:8a:0f", - NAME="eth1" - - :param node: Node to set udev rules on (must be TG node). - :type node: dict - :raises RuntimeError: If setting of udev rules fails. - """ - ssh = SSH() - ssh.connect(node) - - cmd = f"rm -f {InterfaceUtil.__UDEV_IF_RULES_FILE}" - ret_code, _, _ = ssh.exec_command_sudo(cmd) - if int(ret_code) != 0: - raise RuntimeError(f"'{cmd}' failed on '{node[u'host']}'") - - for interface in node[u"interfaces"].values(): - rule = u'SUBSYSTEM==\\"net\\", ACTION==\\"add\\", ATTR{address}' + \ - u'==\\"' + interface[u"mac_address"] + u'\\", NAME=\\"' + \ - interface[u"name"] + u'\\"' - cmd = f"sh -c \"echo '{rule}'\" >> " \ - f"{InterfaceUtil.__UDEV_IF_RULES_FILE}'" - - ret_code, _, _ = ssh.exec_command_sudo(cmd) - if int(ret_code) != 0: - raise RuntimeError(f"'{cmd}' failed on '{node[u'host']}'") - - cmd = u"/etc/init.d/udev restart" - ssh.exec_command_sudo(cmd) - @staticmethod def tg_set_interfaces_default_driver(node): """Set interfaces default driver specified in topology yaml file. @@ -660,7 +626,7 @@ class InterfaceUtil: InterfaceUtil.update_nic_interface_names(node) @staticmethod - def update_tg_interface_data_on_node(node, skip_tg_udev=False): + def update_tg_interface_data_on_node(node): """Update interface name for TG/linux node in DICT__nodes. .. note:: @@ -672,9 +638,7 @@ class InterfaceUtil: "00:00:00:00:00:00": "lo" :param node: Node selected from DICT__nodes. - :param skip_tg_udev: Skip udev rename on TG node. :type node: dict - :type skip_tg_udev: bool :raises RuntimeError: If getting of interface name and MAC fails. """ # First setup interface driver specified in yaml file @@ -699,10 +663,6 @@ class InterfaceUtil: continue interface[u"name"] = name - # Set udev rules for interfaces - if not skip_tg_udev: - InterfaceUtil.tg_set_interfaces_udev_rules(node) - @staticmethod def iface_update_numa_node(node): """For all interfaces from topology file update numa node based on @@ -744,26 +704,9 @@ class InterfaceUtil: else: raise RuntimeError(f"Update numa node failed for: {if_pci}") - @staticmethod - def update_all_numa_nodes(nodes, skip_tg=False): - """For all nodes and all their interfaces from topology file update numa - node information based on information from the node. - - :param nodes: Nodes in the topology. - :param skip_tg: Skip TG node - :type nodes: dict - :type skip_tg: bool - :returns: Nothing. - """ - for node in nodes.values(): - if node[u"type"] == NodeType.DUT: - InterfaceUtil.iface_update_numa_node(node) - elif node[u"type"] == NodeType.TG and not skip_tg: - InterfaceUtil.iface_update_numa_node(node) - @staticmethod def update_all_interface_data_on_all_nodes( - nodes, skip_tg=False, skip_tg_udev=False, numa_node=False): + nodes, skip_tg=False, skip_vpp=False): """Update interface names on all nodes in DICT__nodes. This method updates the topology dictionary by querying interface lists @@ -771,25 +714,17 @@ class InterfaceUtil: :param nodes: Nodes in the topology. :param skip_tg: Skip TG node. - :param skip_tg_udev: Skip udev rename on TG node. - :param numa_node: Retrieve numa_node location. + :param skip_vpp: Skip VPP node. :type nodes: dict :type skip_tg: bool - :type skip_tg_udev: bool - :type numa_node: bool + :type skip_vpp: bool """ - for node_data in nodes.values(): - if node_data[u"type"] == NodeType.DUT: - InterfaceUtil.update_vpp_interface_data_on_node(node_data) - elif node_data[u"type"] == NodeType.TG and not skip_tg: - InterfaceUtil.update_tg_interface_data_on_node( - node_data, skip_tg_udev) - - if numa_node: - if node_data[u"type"] == NodeType.DUT: - InterfaceUtil.iface_update_numa_node(node_data) - elif node_data[u"type"] == NodeType.TG and not skip_tg: - InterfaceUtil.iface_update_numa_node(node_data) + for node in nodes.values(): + if node[u"type"] == NodeType.DUT and not skip_vpp: + InterfaceUtil.update_vpp_interface_data_on_node(node) + elif node[u"type"] == NodeType.TG and not skip_tg: + InterfaceUtil.update_tg_interface_data_on_node(node) + InterfaceUtil.iface_update_numa_node(node) @staticmethod def create_vlan_subinterface(node, interface, vlan): @@ -1138,17 +1073,21 @@ class InterfaceUtil: return if_key @staticmethod - def add_eth_interface(node, ifc_name=None, sw_if_index=None, ifc_pfx=None): + def add_eth_interface( + node, ifc_name=None, sw_if_index=None, ifc_pfx=None, + host_if_key=None): """Add ethernet interface to current topology. :param node: DUT node from topology. :param ifc_name: Name of the interface. :param sw_if_index: SW interface index. :param ifc_pfx: Interface key prefix. + :param host_if_key: Host interface key from topology file. :type node: dict :type ifc_name: str :type sw_if_index: int :type ifc_pfx: str + :type host_if_key: str """ if_key = Topology.add_new_port(node, ifc_pfx) @@ -1161,18 +1100,28 @@ class InterfaceUtil: Topology.update_interface_name(node, if_key, ifc_name) ifc_mac = InterfaceUtil.vpp_get_interface_mac(node, sw_if_index) Topology.update_interface_mac_address(node, if_key, ifc_mac) + if host_if_key is not None: + Topology.set_interface_numa_node( + node, if_key, Topology.get_interface_numa_node( + node, host_if_key + ) + ) + Topology.update_interface_pci_address( + node, if_key, Topology.get_interface_pci_addr(node, host_if_key) + ) @staticmethod - def vpp_create_avf_interface(node, vf_pci_addr, num_rx_queues=None): + def vpp_create_avf_interface(node, if_key, num_rx_queues=None): """Create AVF interface on VPP node. :param node: DUT node from topology. - :param vf_pci_addr: PCI address binded to i40evf driver. + :param if_key: Interface key from topology file of interface + to be bound to i40evf driver. :param num_rx_queues: Number of RX queues. :type node: dict - :type vf_pci_addr: str + :type if_key: str :type num_rx_queues: int - :returns: Interface key (name) in topology. + :returns: AVF interface key (name) in topology. :rtype: str :raises RuntimeError: If it is not possible to create AVF interface on the node. @@ -1182,6 +1131,7 @@ class InterfaceUtil: ) cmd = u"avf_create" + vf_pci_addr = Topology.get_interface_pci_addr(node, if_key) args = dict( pci_addr=InterfaceUtil.pci_to_int(vf_pci_addr), enable_elog=0, @@ -1194,45 +1144,51 @@ class InterfaceUtil: sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg) InterfaceUtil.add_eth_interface( - node, sw_if_index=sw_if_index, ifc_pfx=u"eth_avf" + node, sw_if_index=sw_if_index, ifc_pfx=u"eth_avf", + host_if_key=if_key ) - if_key = Topology.get_interface_by_sw_index(node, sw_if_index) - return if_key + return Topology.get_interface_by_sw_index(node, sw_if_index) @staticmethod - def vpp_create_rdma_interface(node, pci_addr, num_rx_queues=None): + def vpp_create_rdma_interface( + node, if_key, num_rx_queues=None, mode=u"auto"): """Create RDMA interface on VPP node. :param node: DUT node from topology. - :param pci_addr: PCI address binded to rdma-core driver. + :param if_key: Physical interface key from topology file of interface + to be bound to rdma-core driver. :param num_rx_queues: Number of RX queues. + :param mode: RDMA interface mode - auto/ibv/dv. :type node: dict - :type pci_addr: str + :type if_key: str :type num_rx_queues: int - :returns: Interface key (name) in topology. + :type mode: str + :returns: Interface key (name) in topology file. :rtype: str :raises RuntimeError: If it is not possible to create RDMA interface on the node. """ cmd = u"rdma_create" + pci_addr = Topology.get_interface_pci_addr(node, if_key) args = dict( name=InterfaceUtil.pci_to_eth(node, pci_addr), host_if=InterfaceUtil.pci_to_eth(node, pci_addr), rxq_num=int(num_rx_queues) if num_rx_queues else 0, - rxq_size=0, - txq_size=0 + rxq_size=1024, + txq_size=1024, + mode=getattr(RdmaMode,f"RDMA_API_MODE_{mode.upper()}").value, ) err_msg = f"Failed to create RDMA interface on host {node[u'host']}" with PapiSocketExecutor(node) as papi_exec: sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg) InterfaceUtil.add_eth_interface( - node, sw_if_index=sw_if_index, ifc_pfx=u"eth_rdma" + node, sw_if_index=sw_if_index, ifc_pfx=u"eth_rdma", + host_if_key=if_key ) - if_key = Topology.get_interface_by_sw_index(node, sw_if_index) - return if_key + return Topology.get_interface_by_sw_index(node, sw_if_index) @staticmethod def vpp_enslave_physical_interface(node, interface, bond_if): @@ -1606,8 +1562,9 @@ class InterfaceUtil: ) pf_dev = f"`basename /sys/bus/pci/devices/{pf_pci_addr}/net/*`" - InterfaceUtil.set_linux_interface_trust_on(node, pf_dev, - vf_id=vf_id) + InterfaceUtil.set_linux_interface_trust_on( + node, pf_dev, vf_id=vf_id + ) if osi_layer == u"L2": InterfaceUtil.set_linux_interface_spoof_off( node, pf_dev, vf_id=vf_id @@ -1628,6 +1585,11 @@ class InterfaceUtil: ) Topology.update_interface_mac_address(node, vf_ifc_key, vf_mac_addr) Topology.update_interface_pci_address(node, vf_ifc_key, vf_pci_addr) + Topology.set_interface_numa_node( + node, vf_ifc_key, Topology.get_interface_numa_node( + node, ifc_key + ) + ) vf_ifc_keys.append(vf_ifc_key) return vf_ifc_keys