From 7bfb36dfd9284bbca10881e31e14108c7d468b7c Mon Sep 17 00:00:00 2001 From: Jan Gelety Date: Tue, 17 Oct 2017 15:31:05 +0200 Subject: [PATCH 1/1] CSIT-843: Update actual topology in case of new/updated/deleted interface Change-Id: I6adfe86bd0b9cdf3d194a1b871e52481c333d8e7 Signed-off-by: Jan Gelety --- resources/libraries/python/InterfaceUtil.py | 48 +++++-- resources/libraries/python/Memif.py | 157 ++++++++++++++++++++- resources/libraries/python/Tap.py | 72 +++++++++- resources/libraries/python/VhostUser.py | 24 +++- resources/libraries/python/topology.py | 152 +++++++++++++++----- .../robot/performance/performance_setup.robot | 5 + resources/libraries/robot/shared/default.robot | 3 + ...-dot1q-l2bdbasemaclrn-eth-2vhost-1vm-func.robot | 6 +- ...2p-eth-l2bdbasemaclrn-eth-2vhost-1vm-func.robot | 9 +- ...2p-eth-l2bdbasemacstc-eth-2vhost-1vm-func.robot | 9 +- 10 files changed, 407 insertions(+), 78 deletions(-) diff --git a/resources/libraries/python/InterfaceUtil.py b/resources/libraries/python/InterfaceUtil.py index a68b921146..503715c6dd 100644 --- a/resources/libraries/python/InterfaceUtil.py +++ b/resources/libraries/python/InterfaceUtil.py @@ -655,10 +655,14 @@ class InterfaceUtil(object): sw_if_index=sw_if_index, vlan=vlan) if output[0]["retval"] == 0: - sw_subif_index = output[0]["sw_if_index"] + sw_subif_idx = output[0]["sw_if_index"] logger.trace('VLAN subinterface with sw_if_index {} and VLAN ID {} ' - 'created on node {}'.format(sw_subif_index, + 'created on node {}'.format(sw_subif_idx, vlan, node['host'])) + if_key = Topology.add_new_port(node, "vlan_subif") + Topology.update_interface_sw_if_index(node, if_key, sw_subif_idx) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_subif_idx) + Topology.update_interface_name(node, if_key, ifc_name) else: raise RuntimeError('Unable to create VLAN subinterface on node {}' .format(node['host'])) @@ -666,7 +670,7 @@ class InterfaceUtil(object): with VatTerminal(node, False) as vat: vat.vat_terminal_exec_cmd('exec show interfaces') - return '{}.{}'.format(interface, vlan), sw_subif_index + return '{}.{}'.format(interface, vlan), sw_subif_idx @staticmethod def create_vxlan_interface(node, vni, source_ip, destination_ip): @@ -695,9 +699,14 @@ class InterfaceUtil(object): output = output[0] if output["retval"] == 0: - return output["sw_if_index"] + sw_if_idx = output["sw_if_index"] + if_key = Topology.add_new_port(node, "vxlan_tunnel") + Topology.update_interface_sw_if_index(node, if_key, sw_if_idx) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx) + Topology.update_interface_name(node, if_key, ifc_name) + return sw_if_idx else: - raise RuntimeError('Unable to create VXLAN interface on node {0}' + raise RuntimeError("Unable to create VXLAN interface on node {0}" .format(node)) @staticmethod @@ -823,9 +832,13 @@ class InterfaceUtil(object): type_subif=type_subif) if output[0]["retval"] == 0: - sw_subif_index = output[0]["sw_if_index"] + sw_subif_idx = output[0]["sw_if_index"] logger.trace('Created subinterface with index {}' - .format(sw_subif_index)) + .format(sw_subif_idx)) + if_key = Topology.add_new_port(node, "subinterface") + Topology.update_interface_sw_if_index(node, if_key, sw_subif_idx) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_subif_idx) + Topology.update_interface_name(node, if_key, ifc_name) else: raise RuntimeError('Unable to create sub-interface on node {}' .format(node['host'])) @@ -834,7 +847,7 @@ class InterfaceUtil(object): vat.vat_terminal_exec_cmd('exec show interfaces') name = '{}.{}'.format(interface, sub_id) - return name, sw_subif_index + return name, sw_subif_idx @staticmethod def create_gre_tunnel_interface(node, source_ip, destination_ip): @@ -856,14 +869,19 @@ class InterfaceUtil(object): output = output[0] if output["retval"] == 0: - sw_if_index = output["sw_if_index"] + sw_if_idx = output["sw_if_index"] vat_executor = VatExecutor() vat_executor.execute_script_json_out("dump_interfaces.vat", node) interface_dump_json = vat_executor.get_script_stdout() name = VatJsonUtil.get_interface_name_from_json( - interface_dump_json, sw_if_index) - return name, sw_if_index + interface_dump_json, sw_if_idx) + + if_key = Topology.add_new_port(node, "gre_tunnel") + Topology.update_interface_sw_if_index(node, if_key, sw_if_idx) + Topology.update_interface_name(node, if_key, name) + + return name, sw_if_idx else: raise RuntimeError('Unable to create GRE tunnel on node {}.' .format(node)) @@ -881,7 +899,12 @@ class InterfaceUtil(object): """ out = VatExecutor.cmd_from_template(node, "create_loopback.vat") if out[0].get('retval') == 0: - return out[0].get('sw_if_index') + sw_if_idx = out[0].get('sw_if_index') + if_key = Topology.add_new_port(node, "loopback") + Topology.update_interface_sw_if_index(node, if_key, sw_if_idx) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx) + Topology.update_interface_name(node, if_key, ifc_name) + return sw_if_idx else: raise RuntimeError('Create loopback failed on node "{}"' .format(node['host'])) @@ -1067,7 +1090,6 @@ class InterfaceUtil(object): raise RuntimeError('Unable to assign interface to FIB node {}.' .format(node)) - @staticmethod def set_linux_interface_mac(node, interface, mac, namespace=None): """Set MAC address for interface in linux. diff --git a/resources/libraries/python/Memif.py b/resources/libraries/python/Memif.py index 09fa2a8c3e..e3cea939ec 100644 --- a/resources/libraries/python/Memif.py +++ b/resources/libraries/python/Memif.py @@ -15,6 +15,7 @@ from resources.libraries.python.ssh import SSH from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal +from resources.libraries.python.topology import Topology class Memif(object): @@ -24,7 +25,7 @@ class Memif(object): pass @staticmethod - def create_memif_interface(node, socket, mid, role="master"): + def create_memif_interface(node, socket, mid, role='master'): """Create Memif interface on the given node. :param node: Given node to create Memif interface on. @@ -46,13 +47,25 @@ class Memif(object): socket=socket, id=mid, role=role) if 'sw_if_index' in vat.vat_stdout: try: - return int(vat.vat_stdout.split()[4]) + sw_if_idx = int(vat.vat_stdout.split()[4]) + if_key = Topology.add_new_port(node, 'memif') + Topology.update_interface_sw_if_index( + node, if_key, sw_if_idx) + ifc_name = Memif.vpp_get_memif_interface_name( + node, sw_if_idx) + Topology.update_interface_name(node, if_key, ifc_name) + ifc_mac = Memif.vpp_get_memif_interface_mac(node, sw_if_idx) + Topology.update_interface_mac_address(node, if_key, ifc_mac) + Topology.update_interface_memif_socket(node, if_key, socket) + Topology.update_interface_memif_id(node, if_key, mid) + Topology.update_interface_memif_role(node, if_key, role) + return sw_if_idx except KeyError: raise ValueError('Create Memif interface failed on node ' - '{}"'.format(node['host'])) + '{}'.format(node['host'])) else: raise ValueError('Create Memif interface failed on node ' - '{}"'.format(node['host'])) + '{}'.format(node['host'])) @staticmethod def show_memif(node): @@ -78,3 +91,139 @@ class Memif(object): for sock in socks: ssh.exec_command_sudo('rm -f {}'.format(sock)) + + @staticmethod + def parse_memif_dump_data(memif_data): + """Convert Memif data to dictionary. + + :param memif_data: Dump of Memif interfaces data. + :type memif_data: str + :returns: Memif interfaces data in dictionary. + :rtype: dict + :raises RuntimeError: If there is no memif interface name found in + provided data. + """ + memif_name = None + memif_dict = dict() + memif_data = str(memif_data) + values = dict() + + clutter = ['vat#'] + for garbage in clutter: + memif_data = memif_data.replace(garbage, '') + + for line in memif_data.splitlines(): + if line.startswith('Sending') or len(line) == 0: + continue + elif line.startswith('memif'): + if memif_name: + memif_dict[memif_name] = values + line_split = line.split(':', 1) + memif_name = str(line_split[0]) + values = dict() + line = line_split[1] + line_split = line.split() + for i in range(0, len(line_split), 2): + key = str(line_split[i]) + try: + value = line_split[i+1] + except IndexError: + value = None + values[key] = value + if memif_name: + memif_dict[memif_name] = values + else: + raise RuntimeError('No memif interface name found') + + return memif_dict + + @staticmethod + def vpp_get_memif_interface_name(node, sw_if_idx): + """Get Memif interface name from Memif interfaces dump. + + :param node: DUT node. + :param sw_if_idx: DUT node. + :type node: dict + :type sw_if_idx: int + :returns: Memif interface name. + :rtype: str + """ + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template('memif_dump.vat') + memif_data = Memif.parse_memif_dump_data(vat.vat_stdout) + for item in memif_data: + if memif_data[item]['sw_if_index'] == str(sw_if_idx): + return item + return None + + @staticmethod + def vpp_get_memif_interface_mac(node, sw_if_idx): + """Get Memif interface MAC address from Memif interfaces dump. + + :param node: DUT node. + :param sw_if_idx: DUT node. + :type node: dict + :type sw_if_idx: int + :returns: Memif interface MAC address. + :rtype: str + """ + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template('memif_dump.vat') + memif_data = Memif.parse_memif_dump_data(vat.vat_stdout) + for item in memif_data: + if memif_data[item]['sw_if_index'] == str(sw_if_idx): + return memif_data[item].get('mac', None) + + @staticmethod + def vpp_get_memif_interface_socket(node, sw_if_idx): + """Get Memif interface socket path from Memif interfaces dump. + + :param node: DUT node. + :param sw_if_idx: DUT node. + :type node: dict + :type sw_if_idx: int + :returns: Memif interface socket path. + :rtype: str + """ + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template('memif_dump.vat') + memif_data = Memif.parse_memif_dump_data(vat.vat_stdout) + for item in memif_data: + if memif_data[item]['sw_if_index'] == str(sw_if_idx): + return memif_data[item].get('socket', None) + + @staticmethod + def vpp_get_memif_interface_id(node, sw_if_idx): + """Get Memif interface ID from Memif interfaces dump. + + :param node: DUT node. + :param sw_if_idx: DUT node. + :type node: dict + :type sw_if_idx: int + :returns: Memif interface ID. + :rtype: int + """ + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template('memif_dump.vat') + memif_data = Memif.parse_memif_dump_data(vat.vat_stdout) + for item in memif_data: + if memif_data[item]['sw_if_index'] == str(sw_if_idx): + return int(memif_data[item].get('id', None)) + + @staticmethod + def vpp_get_memif_interface_role(node, sw_if_idx): + """Get Memif interface role from Memif interfaces dump. + + :param node: DUT node. + :param sw_if_idx: DUT node. + :type node: dict + :type sw_if_idx: int + :returns: Memif interface role. + :rtype: int + """ + with VatTerminal(node, json_param=False) as vat: + vat.vat_terminal_exec_cmd_from_template('memif_dump.vat') + memif_data = Memif.parse_memif_dump_data(vat.vat_stdout) + for item in memif_data: + if memif_data[item]['sw_if_index'] == str(sw_if_idx): + return memif_data[item].get('role', None) diff --git a/resources/libraries/python/Tap.py b/resources/libraries/python/Tap.py index 6c346860de..cf0ae215ed 100644 --- a/resources/libraries/python/Tap.py +++ b/resources/libraries/python/Tap.py @@ -15,6 +15,7 @@ from resources.libraries.python.VatExecutor import VatTerminal from resources.libraries.python.InterfaceUtil import InterfaceUtil +from resources.libraries.python.topology import Topology class Tap(object): @@ -30,7 +31,7 @@ class Tap(object): :type node: dict :type tap_name: str :type mac: str - :return: Returns a interface index. + :returns: Returns a interface index. :rtype: int """ command = 'connect' @@ -42,7 +43,17 @@ class Tap(object): resp = vat.vat_terminal_exec_cmd_from_template('tap.vat', tap_command=command, tap_arguments=args) - return resp[0]['sw_if_index'] + sw_if_idx = resp[0]['sw_if_index'] + if_key = Topology.add_new_port(node, 'tap') + Topology.update_interface_sw_if_index(node, if_key, sw_if_idx) + ifc_name = Tap.vpp_get_tap_interface_name(node, sw_if_idx) + Topology.update_interface_name(node, if_key, ifc_name) + if mac is None: + mac = Tap.vpp_get_tap_interface_mac(node, sw_if_idx) + Topology.update_interface_mac_address(node, if_key, mac) + Topology.update_interface_tap_dev_name(node, if_key, tap_name) + + return sw_if_idx @staticmethod def modify_tap_interface(node, if_index, tap_name, mac=None): @@ -69,6 +80,11 @@ class Tap(object): resp = vat.vat_terminal_exec_cmd_from_template('tap.vat', tap_command=command, tap_arguments=args) + if_key = Topology.get_interface_by_sw_index(node, if_index) + Topology.update_interface_tap_dev_name(node, if_key, tap_name) + if mac: + Topology.update_interface_mac_address(node, if_key, mac) + return resp[0]['sw_if_index'] @staticmethod @@ -90,6 +106,8 @@ class Tap(object): if int(resp[0]['retval']) != 0: raise RuntimeError( 'Could not remove tap interface: {}'.format(resp)) + if_key = Topology.get_interface_sw_index(node, if_index) + Topology.remove_port(node, if_key) @staticmethod def check_tap_present(node, tap_name): @@ -105,3 +123,53 @@ class Tap(object): if len(tap_if) == 0: raise RuntimeError( 'Tap interface :{} does not exist'.format(tap_name)) + + @staticmethod + def vpp_get_tap_interface_name(node, sw_if_idx): + """Get VPP tap interface name from hardware interfaces dump. + + :param node: DUT node. + :param sw_if_idx: DUT node. + :type node: dict + :type sw_if_idx: int + :returns: VPP tap interface name. + :rtype: str + """ + with VatTerminal(node, json_param=False) as vat: + response = vat.vat_terminal_exec_cmd_from_template( + 'show_hardware_detail.vat') + + for line in str(response[0]).splitlines(): + if line.startswith('tap-'): + line_split = line.split() + if line_split[1] == sw_if_idx: + return line_split[0] + + return None + + @staticmethod + def vpp_get_tap_interface_mac(node, sw_if_idx): + """Get tap interface MAC address from hardware interfaces dump. + + :param node: DUT node. + :param sw_if_idx: DUT node. + :type node: dict + :type sw_if_idx: int + :returns: Tap interface MAC address. + :rtype: str + """ + with VatTerminal(node, json_param=False) as vat: + response = vat.vat_terminal_exec_cmd_from_template( + 'show_hardware_detail.vat') + + tap_if_match = False + for line in str(response[0]).splitlines(): + if tap_if_match: + line_split = line.split() + return line_split[-1] + if line.startswith('tap-'): + line_split = line.split() + if line_split[1] == sw_if_idx: + tap_if_match = True + + return None diff --git a/resources/libraries/python/VhostUser.py b/resources/libraries/python/VhostUser.py index 680d4ae300..2e0ed1eada 100644 --- a/resources/libraries/python/VhostUser.py +++ b/resources/libraries/python/VhostUser.py @@ -14,7 +14,8 @@ """Vhost-user interfaces library.""" from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal -from resources.libraries.python.topology import NodeType +from resources.libraries.python.topology import NodeType, Topology +from resources.libraries.python.InterfaceUtil import InterfaceUtil class VhostUser(object): @@ -28,13 +29,22 @@ class VhostUser(object): :param socket: Vhost-user interface socket path. :type node: dict :type socket: str - :return: SW interface index. + :returns: SW interface index. :rtype: int + :raises RuntimeError: If Vhost-user interface creation failed. """ - out = VatExecutor.cmd_from_template(node, "create_vhost_user_if.vat", + out = VatExecutor.cmd_from_template(node, 'create_vhost_user_if.vat', sock=socket) if out[0].get('retval') == 0: - return out[0].get('sw_if_index') + sw_if_idx = int(out[0].get('sw_if_index')) + if_key = Topology.add_new_port(node, 'vhost') + Topology.update_interface_sw_if_index(node, if_key, sw_if_idx) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx) + Topology.update_interface_name(node, if_key, ifc_name) + ifc_mac = InterfaceUtil.vpp_get_interface_mac(node, sw_if_idx) + Topology.update_interface_mac_address(node, if_key, ifc_mac) + Topology.update_interface_vhost_socket(node, if_key, socket) + return sw_if_idx else: raise RuntimeError('Create Vhost-user interface failed on node ' '"{}"'.format(node['host'])) @@ -47,7 +57,7 @@ class VhostUser(object): :param socket: Vhost-user interface socket path. :type node: dict :type socket: str - :return: Interface name or None if not found. + :returns: Interface name or None if not found. :rtype: str """ for interface in node['interfaces'].values(): @@ -64,7 +74,7 @@ class VhostUser(object): :param sw_if_index: Idx of the specific interface. :type node: dict :type sw_if_index: str - :return: l2_address of the given interface. + :returns: l2_address of the given interface. :rtype: str """ @@ -83,7 +93,7 @@ class VhostUser(object): :param node: VPP node to get interface data from. :type node: dict - :return: nothing + :returns: nothing """ vat = VatExecutor() vat.execute_script("show_vhost.vat", node, json_out=False) diff --git a/resources/libraries/python/topology.py b/resources/libraries/python/topology.py index 791b07053c..4ff68ec43d 100644 --- a/resources/libraries/python/topology.py +++ b/resources/libraries/python/topology.py @@ -87,7 +87,7 @@ class Topology(object): :param ptype: Port type, used as key prefix. :type node: dict :type ptype: str - :return: Port key or None + :returns: Port key or None :rtype: string or None """ max_ports = 1000000 @@ -99,6 +99,21 @@ class Topology(object): break return iface + @staticmethod + def remove_port(node, iface_key): + """Remove required port from active topology. + + :param node: Node to remove port on. + :param: iface_key: Topology key of the interface. + :type node: dict + :type iface_key: str + :returns: Nothing + """ + try: + node['interfaces'].pop(iface_key) + except KeyError: + pass + @staticmethod def remove_all_ports(node, ptype): """Remove all ports with ptype as prefix. @@ -107,12 +122,28 @@ class Topology(object): :param: ptype: Port type, used as key prefix. :type node: dict :type ptype: str - :return: Nothing + :returns: Nothing """ for if_key in list(node['interfaces']): if if_key.startswith(str(ptype)): node['interfaces'].pop(if_key) + @staticmethod + def remove_all_added_ports_on_all_duts_from_topology(nodes): + """Remove all added ports on all DUT nodes in the topology. + + :param nodes: Nodes in the topology. + :type nodes: dict + :returns: Nothing + """ + port_types = ('subinterface', 'vlan_subif', 'memif', 'tap', 'vhost', + 'loopback', 'gre_tunnel', 'vxlan_tunnel') + + for node_data in nodes.values(): + if node_data['type'] == NodeType.DUT: + for ptype in port_types: + Topology.remove_all_ports(node_data, ptype) + @staticmethod def update_interface_sw_if_index(node, iface_key, sw_if_index): """Update sw_if_index on the interface from the node. @@ -165,6 +196,59 @@ class Topology(object): """ node['interfaces'][iface_key]['vhost_socket'] = str(vhost_socket) + @staticmethod + def update_interface_memif_socket(node, iface_key, memif_socket): + """Update memif socket name on the interface from the node. + + :param node: Node to update socket name on. + :param iface_key: Topology key of the interface. + :param memif_socket: Path to named socket on node. + :type node: dict + :type iface_key: str + :type memif_socket: str + """ + node['interfaces'][iface_key]['memif_socket'] = str(memif_socket) + + @staticmethod + def update_interface_memif_id(node, iface_key, memif_id): + """Update memif ID on the interface from the node. + + :param node: Node to update memif ID on. + :param iface_key: Topology key of the interface. + :param memif_id: Memif interface ID. + :type node: dict + :type iface_key: str + :type memif_id: str + """ + node['interfaces'][iface_key]['memif_id'] = str(memif_id) + + @staticmethod + def update_interface_memif_role(node, iface_key, memif_role): + """Update memif role on the interface from the node. + + :param node: Node to update memif role on. + :param iface_key: Topology key of the interface. + :param memif_role: Memif role. + :type node: dict + :type iface_key: str + :type memif_role: str + """ + node['interfaces'][iface_key]['memif_role'] = str(memif_role) + + @staticmethod + def update_interface_tap_dev_name(node, iface_key, dev_name): + """Update device name on the tap interface from the node. + + :param node: Node to update tap device name on. + :param iface_key: Topology key of the interface. + :param dev_name: Device name of the tap interface. + :type node: dict + :type iface_key: str + :type dev_name: str + :returns: Nothing + """ + node['interfaces'][iface_key]['dev_name'] = str(dev_name) + @staticmethod def get_node_by_hostname(nodes, hostname): """Get node from nodes of the topology by hostname. @@ -173,7 +257,7 @@ class Topology(object): :param hostname: Host name. :type nodes: dict :type hostname: str - :return: Node dictionary or None if not found. + :returns: Node dictionary or None if not found. """ for node in nodes.values(): if node['host'] == hostname: @@ -187,7 +271,7 @@ class Topology(object): :param nodes: Nodes of the test topology. :type nodes: dict - :return: Links in the topology. + :returns: Links in the topology. :rtype: list """ links = [] @@ -212,7 +296,7 @@ class Topology(object): :type node: dict :type key: string :type value: string - :return: Interface key from topology file + :returns: Interface key from topology file :rtype: string """ interfaces = node['interfaces'] @@ -236,7 +320,7 @@ class Topology(object): :param iface_name: Interface name (string form). :type node: dict :type iface_name: string - :return: Interface key. + :returns: Interface key. :rtype: str """ return Topology._get_interface_by_key_value(node, "name", iface_name) @@ -252,7 +336,7 @@ class Topology(object): :param link_name: Name of the link that a interface is connected to. :type node: dict :type link_name: string - :return: Interface key of the interface connected to the given link. + :returns: Interface key of the interface connected to the given link. :rtype: str """ return Topology._get_interface_by_key_value(node, "link", link_name) @@ -268,7 +352,7 @@ class Topology(object): connected to. :type node: dict :type link_names: list - :return: Dictionary of interface names that are connected to the given + :returns: Dictionary of interface names that are connected to the given links. :rtype: dict """ @@ -294,7 +378,7 @@ class Topology(object): :param sw_index: Sw_index of the link that a interface is connected to. :type node: dict :type sw_index: int - :return: Interface name of the interface connected to the given link. + :returns: Interface name of the interface connected to the given link. :rtype: str """ return Topology._get_interface_by_key_value(node, "vpp_sw_index", @@ -308,7 +392,7 @@ class Topology(object): :param iface_key: Interface key from topology file, or sw_index. :type node: dict :type iface_key: str/int - :return: Return sw_if_index or None if not found. + :returns: Return sw_if_index or None if not found. """ try: if isinstance(iface_key, basestring): @@ -327,7 +411,7 @@ class Topology(object): :param iface_name: Interface name. :type node: dict :type iface_name: str - :return: Return sw_if_index or None if not found. + :returns: Return sw_if_index or None if not found. :raises TypeError: If provided interface name is not a string. """ try: @@ -348,7 +432,7 @@ class Topology(object): :param iface_key: Interface key from topology file. :type node: dict :type iface_key: str - :return: MTU or None if not found. + :returns: MTU or None if not found. :rtype: int """ try: @@ -365,7 +449,7 @@ class Topology(object): :param iface_key: Interface key from topology file. :type node: dict :type iface_key: str - :return: Interface name or None if not found. + :returns: Interface name or None if not found. :rtype: str """ try: @@ -386,7 +470,7 @@ class Topology(object): :type node: dict :type interface: str or int - :return: Interface key. + :returns: Interface key. :rtype: str :raises TypeError: If provided with invalid interface argument. @@ -428,7 +512,7 @@ class Topology(object): :type interface: str or int :type wanted_format: str - :return: Interface name, interface key or sw_if_index. + :returns: Interface name, interface key or sw_if_index. :rtype: str or int :raises TypeError, ValueError: If provided with invalid arguments. @@ -460,7 +544,7 @@ class Topology(object): :param iface_key: Interface key from topology file. :type node: dict :type iface_key: str - :return: numa node id, None if not available. + :returns: numa node id, None if not available. :rtype: int """ try: @@ -508,7 +592,7 @@ class Topology(object): :param iface_key: Interface key from topology file. :type node: dict :type iface_key: str - :return: Return MAC or None if not found. + :returns: Return MAC or None if not found. """ try: return node['interfaces'][iface_key].get('mac_address') @@ -527,7 +611,7 @@ class Topology(object): :type nodes_info: dict :type node: dict :type iface_key: str - :return: Return (node, interface_key) tuple or None if not found. + :returns: Return (node, interface_key) tuple or None if not found. :rtype: (dict, str) """ link_name = None @@ -562,7 +646,7 @@ class Topology(object): :param iface_key: Interface key from topology file. :type node: dict :type iface_key: str - :return: Return PCI address or None if not found. + :returns: Return PCI address or None if not found. """ try: return node['interfaces'][iface_key].get('pci_address') @@ -577,7 +661,7 @@ class Topology(object): :param iface_key: Interface key from topology file. :type node: dict :type iface_key: str - :return: Return interface driver or None if not found. + :returns: Return interface driver or None if not found. """ try: return node['interfaces'][iface_key].get('driver') @@ -590,7 +674,7 @@ class Topology(object): :param node: Node to get list of interfaces from. :type node: dict - :return: Return list of keys of all interfaces. + :returns: Return list of keys of all interfaces. :rtype: list """ return node['interfaces'].keys() @@ -603,7 +687,7 @@ class Topology(object): :param link_name: Link name. :type node: dict :type link_name: str - :return: MAC address string. + :returns: MAC address string. :rtype: str """ for port in node['interfaces'].values(): @@ -619,7 +703,7 @@ class Topology(object): :param filter_list: Link filter criteria. :type node: dict :type filter_list: list of strings - :return: List of strings that represent link names occupied by the node. + :returns: List of strings representing link names occupied by the node. :rtype: list """ interfaces = node['interfaces'] @@ -631,7 +715,7 @@ class Topology(object): if filt == interface['model']: link_names.append(interface['link']) elif (filter_list is not None) and ('model' not in interface): - logger.trace("Cannot apply filter on interface: {}" + logger.trace('Cannot apply filter on interface: {}' .format(str(interface))) else: link_names.append(interface['link']) @@ -653,7 +737,7 @@ class Topology(object): :type node2: dict :type filter_list_node1: list of strings :type filter_list_node2: list of strings - :return: List of strings that represent connecting link names. + :returns: List of strings that represent connecting link names. :rtype: list """ @@ -685,7 +769,7 @@ class Topology(object): :param node2: Connected node. :type node1: dict :type node2: dict - :return: Name of link connecting the two nodes together. + :returns: Name of link connecting the two nodes together. :rtype: str :raises: RuntimeError """ @@ -704,7 +788,7 @@ class Topology(object): :param node2: Second node. :type node1: dict :type node2: dict - :return: Egress interfaces. + :returns: Egress interfaces. :rtype: list """ interfaces = [] @@ -732,7 +816,7 @@ class Topology(object): :param node2: Second node. :type node1: dict :type node2: dict - :return: Egress interface name. + :returns: Egress interface name. :rtype: str """ interfaces = self.get_egress_interfaces_name_for_nodes(node1, node2) @@ -765,7 +849,7 @@ class Topology(object): :type tgen: dict :type dut1: dict :type dut2: dict - :return: Dictionary of possible link combinations. + :returns: Dictionary of possible link combinations. :rtype: dict """ # TODO: replace with generic function. @@ -789,7 +873,7 @@ class Topology(object): :param node: Node to examine. :type node: dict - :return: True if node is type of TG, otherwise False. + :returns: True if node is type of TG, otherwise False. :rtype: bool """ return node['type'] == NodeType.TG @@ -800,7 +884,7 @@ class Topology(object): :param node: Node created from topology. :type node: dict - :return: Hostname or IP address. + :returns: Hostname or IP address. :rtype: str """ return node['host'] @@ -811,7 +895,7 @@ class Topology(object): :param node: Node created from topology. :type node: dict - :return: Cryptodev configuration string. + :returns: Cryptodev configuration string. :rtype: str """ try: @@ -825,7 +909,7 @@ class Topology(object): :param node: Node created from topology. :type node: dict - :return: uio-driver configuration string. + :returns: uio-driver configuration string. :rtype: str """ try: @@ -841,7 +925,7 @@ class Topology(object): :param iface_key: Interface key from topology file. :type node: dict :type iface_key: str - :return: Return iface_key or None if not found. + :returns: Return iface_key or None if not found. """ try: node['interfaces'][iface_key]['numa_node'] = numa_node_id diff --git a/resources/libraries/robot/performance/performance_setup.robot b/resources/libraries/robot/performance/performance_setup.robot index 434a555dcd..492815b9b6 100644 --- a/resources/libraries/robot/performance/performance_setup.robot +++ b/resources/libraries/robot/performance/performance_setup.robot @@ -437,6 +437,7 @@ | | ... | | [Arguments] | ${rate} | ${framesize} | ${topology_type} | | ... +| | Remove All Added Ports On All DUTs From Topology | ${nodes} | | Show VAT History On All DUTs | ${nodes} | | Show statistics on all DUTs | ${nodes} | | Run Keyword If Test Failed @@ -446,12 +447,14 @@ | Tear down performance ndrchk test | | [Documentation] | Common test teardown for ndrchk performance tests. | | ... +| | Remove All Added Ports On All DUTs From Topology | ${nodes} | | Show VAT History On All DUTs | ${nodes} | | Show statistics on all DUTs | ${nodes} | Tear down performance pdrchk test | | [Documentation] | Common test teardown for pdrchk performance tests. | | ... +| | Remove All Added Ports On All DUTs From Topology | ${nodes} | | Show VAT History On All DUTs | ${nodes} | | Show statistics on all DUTs | ${nodes} @@ -478,6 +481,7 @@ | | ... | ${dut1_node}=${None} | ${dut1_vm_refs}=${None} | | ... | ${dut2_node}=${None} | ${dut2_vm_refs}=${None} | | ... +| | Remove All Added Ports On All DUTs From Topology | ${nodes} | | Show VAT History On All DUTs | ${nodes} | | Show VPP vhost on all DUTs | ${nodes} | | Show statistics on all DUTs | ${nodes} @@ -512,6 +516,7 @@ | | ... | ${dut1_node}=${None} | ${dut1_vm_refs}=${None} | | ... | ${dut2_node}=${None} | ${dut2_vm_refs}=${None} | | ... +| | Remove All Added Ports On All DUTs From Topology | ${nodes} | | Show VAT History On All DUTs | ${nodes} | | Show VPP vhost on all DUTs | ${nodes} | | Show statistics on all DUTs | ${nodes} diff --git a/resources/libraries/robot/shared/default.robot b/resources/libraries/robot/shared/default.robot index fa291bf1aa..555919f9c8 100644 --- a/resources/libraries/robot/shared/default.robot +++ b/resources/libraries/robot/shared/default.robot @@ -312,6 +312,7 @@ | Tear down functional test | | [Documentation] | Common test teardown for functional tests. | | ... +| | Remove All Added Ports On All DUTs From Topology | ${nodes} | | Show Packet Trace on All DUTs | ${nodes} | | Show VAT History On All DUTs | ${nodes} | | Vpp Show Errors On All DUTs | ${nodes} @@ -320,6 +321,7 @@ | Tear down LISP functional test | | [Documentation] | Common test teardown for functional tests with LISP. | | ... +| | Remove All Added Ports On All DUTs From Topology | ${nodes} | | Show Packet Trace on All DUTs | ${nodes} | | Show VAT History On All DUTs | ${nodes} | | Show Vpp Settings | ${nodes['DUT1']} @@ -340,6 +342,7 @@ | | ... | | [Arguments] | ${vm_node} | | ... +| | Remove All Added Ports On All DUTs From Topology | ${nodes} | | Show Packet Trace on All DUTs | ${nodes} | | Show VAT History On All DUTs | ${nodes} | | Show Vpp Settings | ${nodes['DUT1']} diff --git a/tests/vpp/func/vm_vhost/l2bd/eth2p-dot1q-l2bdbasemaclrn-eth-2vhost-1vm-func.robot b/tests/vpp/func/vm_vhost/l2bd/eth2p-dot1q-l2bdbasemaclrn-eth-2vhost-1vm-func.robot index 7eb7d3e857..4eaaefd4fa 100644 --- a/tests/vpp/func/vm_vhost/l2bd/eth2p-dot1q-l2bdbasemaclrn-eth-2vhost-1vm-func.robot +++ b/tests/vpp/func/vm_vhost/l2bd/eth2p-dot1q-l2bdbasemaclrn-eth-2vhost-1vm-func.robot @@ -22,10 +22,8 @@ | Library | resources.libraries.python.Trace | Force Tags | 3_NODE_DOUBLE_LINK_TOPO | HW_ENV | VM_ENV | VPP_VM_ENV | Test Setup | Set up functional test -| Test Teardown | Run Keywords | Show Packet Trace on All DUTs | ${nodes} -| ... | AND | Show vpp trace dump on all DUTs -| ... | AND | Stop and clear QEMU | ${dut_node} | ${vm_node} -| ... | AND | Verify VPP PID in Teardown +| Test Teardown | Run Keywords | Tear down functional test +| ... | AND | Stop and clear QEMU | ${dut_node} | ${vm_node} | Documentation | *L2 bridge domain with VLAN tag over VM test cases* | ... | ... | *[Top] Network Topologies:* TG=DUT 2-node circular topology diff --git a/tests/vpp/func/vm_vhost/l2bd/eth2p-eth-l2bdbasemaclrn-eth-2vhost-1vm-func.robot b/tests/vpp/func/vm_vhost/l2bd/eth2p-eth-l2bdbasemaclrn-eth-2vhost-1vm-func.robot index 678e268235..e7af3f0338 100644 --- a/tests/vpp/func/vm_vhost/l2bd/eth2p-eth-l2bdbasemaclrn-eth-2vhost-1vm-func.robot +++ b/tests/vpp/func/vm_vhost/l2bd/eth2p-eth-l2bdbasemaclrn-eth-2vhost-1vm-func.robot @@ -19,7 +19,8 @@ | Library | resources.libraries.python.Trace | Force Tags | 3_NODE_DOUBLE_LINK_TOPO | HW_ENV | VM_ENV | VPP_VM_ENV | Test Setup | Set up functional test -| Test Teardown | Tear down functional test +| Test Teardown | Run Keywords | Tear down functional test +| ... | AND | Stop and clear QEMU | ${dut_node} | ${vm_node} | Documentation | *L2 bridge-domain test cases* | ... | ... | *[Top] Network Topologies:* TG=DUT=VM 3-node topology with VM @@ -52,9 +53,6 @@ | | ... | switched thru DUT1 and VM in both directions and are correct on | | ... | receive. [Ref] | | ... -| | [Teardown] | Run Keywords | Stop and clear QEMU | ${dut_node} | ${vm_node} -| | ... | AND | Tear down functional test -| | ... | | Given Configure path in 2-node circular topology | | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['TG']} | | And Set interfaces in 2-node circular topology up @@ -85,9 +83,6 @@ | | ... | switched thru DUT1 and VM in both directions and are correct on | | ... | receive. [Ref] | | ... -| | [Teardown] | Run Keywords | Stop and clear QEMU | ${dut_node} | ${vm_node} -| | ... | AND | Tear down functional test -| | ... | | Given Configure path in 2-node circular topology | | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['TG']} | | And Set interfaces in 2-node circular topology up diff --git a/tests/vpp/func/vm_vhost/l2bd/eth2p-eth-l2bdbasemacstc-eth-2vhost-1vm-func.robot b/tests/vpp/func/vm_vhost/l2bd/eth2p-eth-l2bdbasemacstc-eth-2vhost-1vm-func.robot index 22ec61d395..18ad1b77c3 100644 --- a/tests/vpp/func/vm_vhost/l2bd/eth2p-eth-l2bdbasemacstc-eth-2vhost-1vm-func.robot +++ b/tests/vpp/func/vm_vhost/l2bd/eth2p-eth-l2bdbasemacstc-eth-2vhost-1vm-func.robot @@ -19,7 +19,8 @@ | Library | resources.libraries.python.Trace | Force Tags | 3_NODE_DOUBLE_LINK_TOPO | HW_ENV | VM_ENV | VPP_VM_ENV | Test Setup | Set up functional test -| Test Teardown | Tear down functional test +| Test Teardown | Run Keywords | Tear down functional test +| ... | AND | Stop and clear QEMU | ${dut_node} | ${vm_node} | Documentation | *L2 bridge-domain test cases* | ... | ... | *[Top] Network Topologies:* TG=DUT=VM 3-node topology with VM @@ -52,9 +53,6 @@ | | ... | switched thru DUT1 and VM in both directions and are correct on | | ... | receive. [Ref] | | ... -| | [Teardown] | Run Keywords | Stop and clear QEMU | ${dut_node} | ${vm_node} -| | ... | AND | Tear down functional test -| | ... | | Given Configure path in 2-node circular topology | | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['TG']} | | And Set interfaces in 2-node circular topology up @@ -105,9 +103,6 @@ | | ... | switched thru DUT1 and VM in both directions and are correct on | | ... | receive. [Ref] | | ... -| | [Teardown] | Run Keywords | Stop and clear QEMU | ${dut_node} | ${vm_node} -| | ... | AND | Tear down functional test -| | ... | | Given Configure path in 2-node circular topology | | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['TG']} | | And Set interfaces in 2-node circular topology up -- 2.16.6