X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FInterfaceUtil.py;h=11ddf7f91379e29349feed707f86f6eb1deafc70;hp=7706c14e0666f0febd64625e6fe8aa1bc3f69ce9;hb=8fef592605b149fb207b6617678c721ab8453c94;hpb=dbe149c85501bc15dde1496a722e2b9dce86ee92 diff --git a/resources/libraries/python/InterfaceUtil.py b/resources/libraries/python/InterfaceUtil.py index 7706c14e06..11ddf7f913 100644 --- a/resources/libraries/python/InterfaceUtil.py +++ b/resources/libraries/python/InterfaceUtil.py @@ -13,7 +13,6 @@ """Interface util library.""" -from socket import AF_INET, AF_INET6, inet_ntop from time import sleep from enum import IntEnum @@ -24,7 +23,7 @@ from resources.libraries.python.Constants import Constants from resources.libraries.python.CpuUtils import CpuUtils from resources.libraries.python.DUTSetup import DUTSetup from resources.libraries.python.L2Util import L2Util -from resources.libraries.python.PapiExecutor import PapiExecutor +from resources.libraries.python.PapiExecutor import PapiSocketExecutor from resources.libraries.python.parsers.JsonParser import JsonParser from resources.libraries.python.ssh import SSH, exec_cmd_no_error from resources.libraries.python.topology import NodeType, Topology @@ -138,9 +137,8 @@ class InterfaceUtil(object): host=node['host']) args = dict(sw_if_index=sw_if_index, admin_up_down=admin_up_down) - with PapiExecutor(node) as papi_exec: - papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + papi_exec.add(cmd, **args).get_reply(err_msg) elif node['type'] == NodeType.TG or node['type'] == NodeType.VM: cmd = 'ip link set {ifc} {state}'.format( ifc=iface_name, state=state) @@ -210,9 +208,13 @@ class InterfaceUtil(object): host=node['host']) args = dict(sw_if_index=sw_if_index, mtu=int(mtu)) - with PapiExecutor(node) as papi_exec: - papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + try: + with PapiSocketExecutor(node) as papi_exec: + papi_exec.add(cmd, **args).get_reply(err_msg) + except AssertionError as err: + # TODO: Make failure tolerance optional. + logger.debug("Setting MTU failed. Expected?\n{err}".format( + err=err)) @staticmethod def vpp_set_interfaces_mtu_on_node(node, mtu=9200): @@ -302,6 +304,21 @@ class InterfaceUtil(object): :raises TypeError: if the data type of interface is neither basestring nor int. """ + def process_if_dump(if_dump): + """Process interface dump. + + :param if_dump: Interface dump. + :type if_dump: dict + :returns: Processed interface dump. + :rtype: dict + """ + if_dump['interface_name'] = if_dump['interface_name'].rstrip('\x00') + if_dump['tag'] = if_dump['tag'].rstrip('\x00') + if_dump['l2_address'] = L2Util.bin_to_mac(if_dump['l2_address']) + if_dump['b_dmac'] = L2Util.bin_to_mac(if_dump['b_dmac']) + if_dump['b_smac'] = L2Util.bin_to_mac(if_dump['b_smac']) + return if_dump + if interface is not None: if isinstance(interface, basestring): param = 'interface_name' @@ -314,38 +331,19 @@ class InterfaceUtil(object): param = '' cmd = 'sw_interface_dump' - cmd_reply = 'sw_interface_details' args = dict(name_filter_valid=0, name_filter='') err_msg = 'Failed to get interface dump on host {host}'.format( host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_dump(err_msg) - - papi_if_dump = papi_resp.reply[0]['api_reply'] - - def process_if_dump(if_dump): - """Process interface dump. - - :param if_dump: Interface dump. - :type if_dump: dict - :returns: Processed interface dump. - :rtype: dict - """ - if_dump['interface_name'] = if_dump['interface_name'].rstrip('\x00') - if_dump['tag'] = if_dump['tag'].rstrip('\x00') - if_dump['l2_address'] = L2Util.bin_to_mac(if_dump['l2_address']) - if_dump['b_dmac'] = L2Util.bin_to_mac(if_dump['b_dmac']) - if_dump['b_smac'] = L2Util.bin_to_mac(if_dump['b_smac']) - return if_dump + with PapiSocketExecutor(node) as papi_exec: + details = papi_exec.add(cmd, **args).get_details(err_msg) data = list() if interface is None else dict() - for item in papi_if_dump: + for dump in details: if interface is None: - data.append(process_if_dump(item[cmd_reply])) - elif str(item[cmd_reply].get(param)).rstrip('\x00') == \ - str(interface): - data = process_if_dump(item[cmd_reply]) + data.append(process_if_dump(dump)) + elif str(dump.get(param)).rstrip('\x00') == str(interface): + data = process_if_dump(dump) break logger.debug('Interface data:\n{if_data}'.format(if_data=data)) @@ -712,35 +710,33 @@ class InterfaceUtil(object): """Create VLAN sub-interface on node. :param node: Node to add VLAN subinterface on. - :param interface: Interface name on which create VLAN subinterface. + :param interface: Interface name or index on which create VLAN + subinterface. :param vlan: VLAN ID of the subinterface to be created. :type node: dict - :type interface: str + :type interface: str on int :type vlan: int :returns: Name and index of created subinterface. :rtype: tuple :raises RuntimeError: if it is unable to create VLAN subinterface on the - node. + node or interface cannot be converted. """ - iface_key = Topology.get_interface_by_name(node, interface) - sw_if_index = Topology.get_interface_sw_index(node, iface_key) + sw_if_index = InterfaceUtil.get_interface_index(node, interface) cmd = 'create_vlan_subif' args = dict(sw_if_index=sw_if_index, vlan_id=int(vlan)) err_msg = 'Failed to create VLAN sub-interface on host {host}'.format( host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg) - sw_if_idx = papi_resp['sw_if_index'] if_key = Topology.add_new_port(node, 'vlan_subif') - 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_sw_if_index(node, if_key, sw_if_index) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_index) Topology.update_interface_name(node, if_key, ifc_name) - return '{ifc}.{vlan}'.format(ifc=interface, vlan=vlan), sw_if_idx + return '{ifc}.{vlan}'.format(ifc=interface, vlan=vlan), sw_if_index @staticmethod def create_vxlan_interface(node, vni, source_ip, destination_ip): @@ -774,17 +770,42 @@ class InterfaceUtil(object): vni=int(vni)) err_msg = 'Failed to create VXLAN tunnel interface on host {host}'.\ format(host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg) - sw_if_idx = papi_resp['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_sw_if_index(node, if_key, sw_if_index) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_index) Topology.update_interface_name(node, if_key, ifc_name) - return sw_if_idx + return sw_if_index + + @staticmethod + def set_vxlan_bypass(node, interface=None): + """Add the 'ip4-vxlan-bypass' graph node for a given interface. + + By adding the IPv4 vxlan-bypass graph node to an interface, the node + checks for and validate input vxlan packet and bypass ip4-lookup, + ip4-local, ip4-udp-lookup nodes to speedup vxlan packet forwarding. + This node will cause extra overhead to for non-vxlan packets which is + kept at a minimum. + + :param node: Node where to set VXLAN bypass. + :param interface: Numeric index or name string of a specific interface. + :type node: dict + :type interface: int or str + :raises RuntimeError: if it failed to set VXLAN bypass on interface. + """ + sw_if_index = InterfaceUtil.get_interface_index(node, interface) + + cmd = 'sw_interface_set_vxlan_bypass' + args = dict(is_ipv6=0, + sw_if_index=sw_if_index, + enable=1) + err_msg = 'Failed to set VXLAN bypass on interface on host {host}'.\ + format(host=node['host']) + with PapiSocketExecutor(node) as papi_exec: + papi_exec.add(cmd, **args).get_replies(err_msg) @staticmethod def vxlan_dump(node, interface=None): @@ -801,21 +822,6 @@ class InterfaceUtil(object): :raises TypeError: if the data type of interface is neither basestring nor int. """ - if interface is not None: - sw_if_index = InterfaceUtil.get_interface_index(node, interface) - else: - sw_if_index = int(Constants.BITWISE_NON_ZERO) - - cmd = 'vxlan_tunnel_dump' - cmd_reply = 'vxlan_tunnel_details' - args = dict(sw_if_index=sw_if_index) - err_msg = 'Failed to get VXLAN dump on host {host}'.format( - host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_dump(err_msg) - - papi_vxlan_dump = papi_resp.reply[0]['api_reply'] - def process_vxlan_dump(vxlan_dump): """Process vxlan dump. @@ -826,22 +832,34 @@ class InterfaceUtil(object): """ if vxlan_dump['is_ipv6']: vxlan_dump['src_address'] = \ - inet_ntop(AF_INET6, vxlan_dump['src_address']) + ip_address(unicode(vxlan_dump['src_address'])) vxlan_dump['dst_address'] = \ - inet_ntop(AF_INET6, vxlan_dump['dst_address']) + ip_address(unicode(vxlan_dump['dst_address'])) else: vxlan_dump['src_address'] = \ - inet_ntop(AF_INET, vxlan_dump['src_address'][0:4]) + ip_address(unicode(vxlan_dump['src_address'][0:4])) vxlan_dump['dst_address'] = \ - inet_ntop(AF_INET, vxlan_dump['dst_address'][0:4]) + ip_address(unicode(vxlan_dump['dst_address'][0:4])) return vxlan_dump + if interface is not None: + sw_if_index = InterfaceUtil.get_interface_index(node, interface) + else: + sw_if_index = int(Constants.BITWISE_NON_ZERO) + + cmd = 'vxlan_tunnel_dump' + args = dict(sw_if_index=sw_if_index) + err_msg = 'Failed to get VXLAN dump on host {host}'.format( + host=node['host']) + with PapiSocketExecutor(node) as papi_exec: + details = papi_exec.add(cmd, **args).get_details(err_msg) + data = list() if interface is None else dict() - for item in papi_vxlan_dump: + for dump in details: if interface is None: - data.append(process_vxlan_dump(item[cmd_reply])) - elif item[cmd_reply]['sw_if_index'] == sw_if_index: - data = process_vxlan_dump(item[cmd_reply]) + data.append(process_vxlan_dump(dump)) + elif dump['sw_if_index'] == sw_if_index: + data = process_vxlan_dump(dump) break logger.debug('VXLAN data:\n{vxlan_data}'.format(vxlan_data=data)) @@ -858,15 +876,6 @@ class InterfaceUtil(object): :returns: List of dictionaries with all vhost-user interfaces. :rtype: list """ - cmd = 'sw_interface_vhost_user_dump' - cmd_reply = 'sw_interface_vhost_user_details' - err_msg = 'Failed to get vhost-user dump on host {host}'.format( - host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd).get_dump(err_msg) - - papi_vxlan_dump = papi_resp.reply[0]['api_reply'] - def process_vhost_dump(vhost_dump): """Process vhost dump. @@ -881,67 +890,19 @@ class InterfaceUtil(object): vhost_dump['sock_filename'].rstrip('\x00') return vhost_dump - data = list() - for item in papi_vxlan_dump: - data.append(process_vhost_dump(item[cmd_reply])) - - logger.debug('Vhost-user data:\n{vhost_data}'.format(vhost_data=data)) - return data - - @staticmethod - def tap_dump(node, name=None): - """Get all TAP interface data from the given node, or data about - a specific TAP interface. - - TODO: Move to Tap.py - - :param node: VPP node to get data from. - :param name: Optional name of a specific TAP interface. - :type node: dict - :type name: str - :returns: Dictionary of information about a specific TAP interface, or - a List of dictionaries containing all TAP data for the given node. - :rtype: dict or list - """ - cmd = 'sw_interface_tap_v2_dump' - cmd_reply = 'sw_interface_tap_v2_details' - err_msg = 'Failed to get TAP dump on host {host}'.format( + cmd = 'sw_interface_vhost_user_dump' + err_msg = 'Failed to get vhost-user dump on host {host}'.format( host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd).get_dump(err_msg) + with PapiSocketExecutor(node) as papi_exec: + details = papi_exec.add(cmd).get_details(err_msg) - papi_tap_dump = papi_resp.reply[0]['api_reply'] + for dump in details: + # In-place edits. + process_vhost_dump(dump) - def process_tap_dump(tap_dump): - """Process tap dump. - - :param tap_dump: Tap interface dump. - :type tap_dump: dict - :returns: Processed tap interface dump. - :rtype: dict - """ - tap_dump['dev_name'] = tap_dump['dev_name'].rstrip('\x00') - tap_dump['host_if_name'] = tap_dump['host_if_name'].rstrip('\x00') - tap_dump['host_namespace'] = \ - tap_dump['host_namespace'].rstrip('\x00') - tap_dump['host_mac_addr'] = \ - L2Util.bin_to_mac(tap_dump['host_mac_addr']) - tap_dump['host_ip4_addr'] = \ - inet_ntop(AF_INET, tap_dump['host_ip4_addr']) - tap_dump['host_ip6_addr'] = \ - inet_ntop(AF_INET6, tap_dump['host_ip6_addr']) - return tap_dump - - data = list() if name is None else dict() - for item in papi_tap_dump: - if name is None: - data.append(process_tap_dump(item[cmd_reply])) - elif item[cmd_reply].get('dev_name').rstrip('\x00') == name: - data = process_tap_dump(item[cmd_reply]) - break - - logger.debug('TAP data:\n{tap_data}'.format(tap_data=data)) - return data + logger.debug('Vhost-user details:\n{vhost_details}'.format( + vhost_details=details)) + return details @staticmethod def create_subinterface(node, interface, sub_id, outer_vlan_id=None, @@ -985,17 +946,15 @@ class InterfaceUtil(object): inner_vlan_id=int(inner_vlan_id) if inner_vlan_id else 0) err_msg = 'Failed to create sub-interface on host {host}'.format( host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg) - sw_subif_idx = papi_resp['sw_if_index'] 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_sw_if_index(node, if_key, sw_if_index) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_index) Topology.update_interface_name(node, if_key, ifc_name) - return '{ifc}.{s_id}'.format(ifc=interface, s_id=sub_id), sw_subif_idx + return '{ifc}.{s_id}'.format(ifc=interface, s_id=sub_id), sw_if_index @staticmethod def create_gre_tunnel_interface(node, source_ip, destination_ip): @@ -1022,44 +981,45 @@ class InterfaceUtil(object): tunnel=tunnel) err_msg = 'Failed to create GRE tunnel interface on host {host}'.format( host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg) - sw_if_idx = papi_resp['sw_if_index'] if_key = Topology.add_new_port(node, 'gre_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_sw_if_index(node, if_key, sw_if_index) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_index) Topology.update_interface_name(node, if_key, ifc_name) - return ifc_name, sw_if_idx + return ifc_name, sw_if_index @staticmethod - def vpp_create_loopback(node): + def vpp_create_loopback(node, mac=None): """Create loopback interface on VPP node. :param node: Node to create loopback interface on. + :param mac: Optional MAC address for Loopback interface. :type node: dict + :type mac: str :returns: SW interface index. :rtype: int :raises RuntimeError: If it is not possible to create loopback on the node. """ cmd = 'create_loopback' - args = dict(mac_address=0) + args = dict(mac_address=L2Util.mac_to_bin(mac) if mac else 0) err_msg = 'Failed to create loopback interface on host {host}'.format( host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg) - sw_if_idx = papi_resp['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_sw_if_index(node, if_key, sw_if_index) + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_index) Topology.update_interface_name(node, if_key, ifc_name) + if mac: + mac = InterfaceUtil.vpp_get_interface_mac(node, ifc_name) + Topology.update_interface_mac_address(node, if_key, mac) - return sw_if_idx + return sw_if_index @staticmethod def vpp_create_bond_interface(node, mode, load_balance=None, mac=None): @@ -1090,39 +1050,38 @@ class InterfaceUtil(object): lb=load_balance.upper())).value) err_msg = 'Failed to create bond interface on host {host}'.format( host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg) - sw_if_idx = papi_resp['sw_if_index'] - InterfaceUtil.add_eth_interface(node, sw_if_idx=sw_if_idx, + InterfaceUtil.add_eth_interface(node, sw_if_index=sw_if_index, ifc_pfx='eth_bond') - if_key = Topology.get_interface_by_sw_index(node, sw_if_idx) + if_key = Topology.get_interface_by_sw_index(node, sw_if_index) return if_key @staticmethod - def add_eth_interface(node, ifc_name=None, sw_if_idx=None, ifc_pfx=None): + def add_eth_interface(node, ifc_name=None, sw_if_index=None, ifc_pfx=None): """Add ethernet interface to current topology. :param node: DUT node from topology. :param ifc_name: Name of the interface. - :param sw_if_idx: SW interface index. + :param sw_if_index: SW interface index. :param ifc_pfx: Interface key prefix. :type node: dict :type ifc_name: str - :type sw_if_idx: int + :type sw_if_index: int :type ifc_pfx: str """ if_key = Topology.add_new_port(node, ifc_pfx) - if ifc_name and sw_if_idx is None: - sw_if_idx = InterfaceUtil.vpp_get_interface_sw_index(node, ifc_name) - Topology.update_interface_sw_if_index(node, if_key, sw_if_idx) - if sw_if_idx and ifc_name is None: - ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx) + if ifc_name and sw_if_index is None: + sw_if_index = InterfaceUtil.vpp_get_interface_sw_index( + node, ifc_name) + Topology.update_interface_sw_if_index(node, if_key, sw_if_index) + if sw_if_index and ifc_name is None: + ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_index) Topology.update_interface_name(node, if_key, ifc_name) - ifc_mac = InterfaceUtil.vpp_get_interface_mac(node, sw_if_idx) + ifc_mac = InterfaceUtil.vpp_get_interface_mac(node, sw_if_index) Topology.update_interface_mac_address(node, if_key, ifc_mac) @staticmethod @@ -1148,14 +1107,12 @@ class InterfaceUtil(object): txq_size=0) err_msg = 'Failed to create AVF interface on host {host}'.format( host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg) - sw_if_idx = papi_resp['sw_if_index'] - InterfaceUtil.add_eth_interface(node, sw_if_idx=sw_if_idx, + InterfaceUtil.add_eth_interface(node, sw_if_index=sw_if_index, ifc_pfx='eth_avf') - if_key = Topology.get_interface_by_sw_index(node, sw_if_idx) + if_key = Topology.get_interface_by_sw_index(node, sw_if_index) return if_key @@ -1182,56 +1139,45 @@ class InterfaceUtil(object): 'interface {bond} on host {host}'.format(ifc=interface, bond=bond_if, host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + papi_exec.add(cmd, **args).get_reply(err_msg) @staticmethod - def vpp_show_bond_data_on_node(node, details=False): + def vpp_show_bond_data_on_node(node, verbose=False): """Show (detailed) bond information on VPP node. :param node: DUT node from topology. - :param details: If detailed information is required or not. + :param verbose: If detailed information is required or not. :type node: dict - :type details: bool + :type verbose: bool """ cmd = 'sw_interface_bond_dump' - cmd_reply = 'sw_interface_bond_details' err_msg = 'Failed to get bond interface dump on host {host}'.format( host=node['host']) data = ('Bond data on node {host}:\n'.format(host=node['host'])) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd).get_dump(err_msg) - - papi_dump = papi_resp.reply[0]['api_reply'] - for item in papi_dump: - data += ('{b}\n'.format(b=item[cmd_reply]['interface_name']. - rstrip('\x00'))) - data += (' mode: {m}\n'. - format(m=LinkBondMode(item[cmd_reply]['mode']).name. - lower())) - data += (' load balance: {lb}\n'. - format(lb=LinkBondLoadBalance(item[cmd_reply]['lb']).name. - lower())) - data += (' number of active slaves: {n}\n'. - format(n=item[cmd_reply]['active_slaves'])) - if details: + with PapiSocketExecutor(node) as papi_exec: + details = papi_exec.add(cmd).get_details(err_msg) + + for bond in details: + data += ('{b}\n'.format(b=bond['interface_name'].rstrip('\x00'))) + data += (' mode: {m}\n'.format(m=bond['mode']).lower()) + data += (' load balance: {lb}\n'.format(lb=bond['lb']).lower()) + data += (' number of active slaves: {n}\n'.format( + n=bond['active_slaves'])) + if verbose: slave_data = InterfaceUtil.vpp_bond_slave_dump( node, Topology.get_interface_by_sw_index( - node, item[cmd_reply]['sw_if_index'])) + node, bond['sw_if_index'])) for slave in slave_data: if not slave['is_passive']: data += (' {s}\n'.format(s=slave['interface_name'])) - data += (' number of slaves: {n}\n'. - format(n=item[cmd_reply]['slaves'])) - if details: + data += (' number of slaves: {n}\n'.format(n=bond['slaves'])) + if verbose: for slave in slave_data: data += (' {s}\n'.format(s=slave['interface_name'])) - data += (' interface id: {i}\n'. - format(i=item[cmd_reply]['id'])) - data += (' sw_if_index: {i}\n'. - format(i=item[cmd_reply]['sw_if_index'])) + data += (' interface id: {i}\n'.format(i=bond['id'])) + data += (' sw_if_index: {i}\n'.format(i=bond['sw_if_index'])) logger.info(data) @staticmethod @@ -1245,18 +1191,6 @@ class InterfaceUtil(object): :returns: Bond slave interface data. :rtype: dict """ - cmd = 'sw_interface_slave_dump' - cmd_reply = 'sw_interface_slave_details' - args = dict(sw_if_index=Topology.get_interface_sw_index( - node, interface)) - err_msg = 'Failed to get slave dump on host {host}'.format( - host=node['host']) - - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_dump(err_msg) - - papi_dump = papi_resp.reply[0]['api_reply'] - def process_slave_dump(slave_dump): """Process slave dump. @@ -1269,25 +1203,34 @@ class InterfaceUtil(object): rstrip('\x00') return slave_dump - data = list() - for item in papi_dump: - data.append(process_slave_dump(item[cmd_reply])) + cmd = 'sw_interface_slave_dump' + args = dict(sw_if_index=Topology.get_interface_sw_index( + node, interface)) + err_msg = 'Failed to get slave dump on host {host}'.format( + host=node['host']) - logger.debug('Slave data:\n{slave_data}'.format(slave_data=data)) - return data + with PapiSocketExecutor(node) as papi_exec: + details = papi_exec.add(cmd, **args).get_details(err_msg) + + for dump in details: + # In-place edits. + process_slave_dump(dump) + + logger.debug('Slave data:\n{slave_data}'.format(slave_data=details)) + return details @staticmethod - def vpp_show_bond_data_on_all_nodes(nodes, details=False): + def vpp_show_bond_data_on_all_nodes(nodes, verbose=False): """Show (detailed) bond information on all VPP nodes in DICT__nodes. :param nodes: Nodes in the topology. - :param details: If detailed information is required or not. + :param verbose: If detailed information is required or not. :type nodes: dict - :type details: bool + :type verbose: bool """ for node_data in nodes.values(): if node_data['type'] == NodeType.DUT: - InterfaceUtil.vpp_show_bond_data_on_node(node_data, details) + InterfaceUtil.vpp_show_bond_data_on_node(node_data, verbose) @staticmethod def vpp_enable_input_acl_interface(node, interface, ip_version, @@ -1315,9 +1258,8 @@ class InterfaceUtil(object): is_add=1) err_msg = 'Failed to enable input acl on interface {ifc}'.format( ifc=interface) - with PapiExecutor(node) as papi_exec: - papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + papi_exec.add(cmd, **args).get_reply(err_msg) @staticmethod def get_interface_classify_table(node, interface): @@ -1341,11 +1283,10 @@ class InterfaceUtil(object): args = dict(sw_if_index=sw_if_index) err_msg = 'Failed to get classify table name by interface {ifc}'.format( ifc=interface) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg). \ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + reply = papi_exec.add(cmd, **args).get_reply(err_msg) - return papi_resp + return reply @staticmethod def get_sw_if_index(node, interface_name): @@ -1376,22 +1317,6 @@ class InterfaceUtil(object): interfaces. :rtype: dict or list """ - if interface_name is not None: - sw_if_index = InterfaceUtil.get_interface_index( - node, interface_name) - else: - sw_if_index = int(Constants.BITWISE_NON_ZERO) - - cmd = 'vxlan_gpe_tunnel_dump' - cmd_reply = 'vxlan_gpe_tunnel_details' - args = dict(sw_if_index=sw_if_index) - err_msg = 'Failed to get VXLAN-GPE dump on host {host}'.format( - host=node['host']) - with PapiExecutor(node) as papi_exec: - papi_resp = papi_exec.add(cmd, **args).get_dump(err_msg) - - papi_vxlan_dump = papi_resp.reply[0]['api_reply'] - def process_vxlan_gpe_dump(vxlan_dump): """Process vxlan_gpe dump. @@ -1402,22 +1327,35 @@ class InterfaceUtil(object): """ if vxlan_dump['is_ipv6']: vxlan_dump['local'] = \ - inet_ntop(AF_INET6, vxlan_dump['local']) + ip_address(unicode(vxlan_dump['local'])) vxlan_dump['remote'] = \ - inet_ntop(AF_INET6, vxlan_dump['remote']) + ip_address(unicode(vxlan_dump['remote'])) else: vxlan_dump['local'] = \ - inet_ntop(AF_INET, vxlan_dump['local'][0:4]) + ip_address(unicode(vxlan_dump['local'][0:4])) vxlan_dump['remote'] = \ - inet_ntop(AF_INET, vxlan_dump['remote'][0:4]) + ip_address(unicode(vxlan_dump['remote'][0:4])) return vxlan_dump + if interface_name is not None: + sw_if_index = InterfaceUtil.get_interface_index( + node, interface_name) + else: + sw_if_index = int(Constants.BITWISE_NON_ZERO) + + cmd = 'vxlan_gpe_tunnel_dump' + args = dict(sw_if_index=sw_if_index) + err_msg = 'Failed to get VXLAN-GPE dump on host {host}'.format( + host=node['host']) + with PapiSocketExecutor(node) as papi_exec: + details = papi_exec.add(cmd, **args).get_details(err_msg) + data = list() if interface_name is None else dict() - for item in papi_vxlan_dump: + for dump in details: if interface_name is None: - data.append(process_vxlan_gpe_dump(item[cmd_reply])) - elif item[cmd_reply]['sw_if_index'] == sw_if_index: - data = process_vxlan_gpe_dump(item[cmd_reply]) + data.append(process_vxlan_gpe_dump(dump)) + elif dump['sw_if_index'] == sw_if_index: + data = process_vxlan_gpe_dump(dump) break logger.debug('VXLAN-GPE data:\n{vxlan_gpe_data}'.format( @@ -1444,9 +1382,8 @@ class InterfaceUtil(object): vrf_id=int(table_id)) err_msg = 'Failed to assign interface {ifc} to FIB table'.format( ifc=interface) - with PapiExecutor(node) as papi_exec: - papi_exec.add(cmd, **args).get_replies(err_msg). \ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + papi_exec.add(cmd, **args).get_reply(err_msg) @staticmethod def set_linux_interface_mac(node, interface, mac, namespace=None, @@ -1518,12 +1455,12 @@ class InterfaceUtil(object): @staticmethod def init_avf_interface(node, ifc_key, numvfs=1, osi_layer='L2'): - """Init PCI device by creating VFs and bind them to vfio-pci for AVF + """Init PCI device by creating VIFs and bind them to vfio-pci for AVF driver testing on DUT. :param node: DUT node. :param ifc_key: Interface key from topology file. - :param numvfs: Number of VFs to initialize, 0 - disable the VFs. + :param numvfs: Number of VIFs to initialize, 0 - disable the VIFs. :param osi_layer: OSI Layer type to initialize TG with. Default value "L2" sets linux interface spoof off. :type node: dict @@ -1539,10 +1476,11 @@ class InterfaceUtil(object): pf_mac_addr = Topology.get_interface_mac(node, ifc_key).split(":") uio_driver = Topology.get_uio_driver(node) kernel_driver = Topology.get_interface_driver(node, ifc_key) - if kernel_driver != "i40e": + if kernel_driver not in ("i40e", "i40evf"): raise RuntimeError( - "AVF needs i40e driver, not {driver} at node {host} ifc {ifc}"\ - .format(driver=kernel_driver, host=node["host"], ifc=ifc_key)) + "AVF needs i40e-compatible driver, not {driver} at node {host}" + " ifc {ifc}".format( + driver=kernel_driver, host=node["host"], ifc=ifc_key)) current_driver = DUTSetup.get_pci_dev_driver( node, pf_pci_addr.replace(':', r'\:')) @@ -1556,7 +1494,7 @@ class InterfaceUtil(object): # Bind to kernel driver. DUTSetup.pci_driver_bind(node, pf_pci_addr, kernel_driver) - # Initialize PCI VFs + # Initialize PCI VFs. DUTSetup.set_sriov_numvfs(node, pf_pci_addr, numvfs) vf_ifc_keys = [] @@ -1580,7 +1518,7 @@ class InterfaceUtil(object): DUTSetup.pci_vf_driver_bind(node, pf_pci_addr, vf_id, uio_driver) # Add newly created ports into topology file - vf_ifc_name = '{pf_if_key}_vf'.format(pf_if_key=ifc_key) + vf_ifc_name = '{pf_if_key}_vif'.format(pf_if_key=ifc_key) vf_pci_addr = DUTSetup.get_virtfn_pci_addr(node, pf_pci_addr, vf_id) vf_ifc_key = Topology.add_new_port(node, vf_ifc_name) Topology.update_interface_name(node, vf_ifc_key, @@ -1601,17 +1539,14 @@ class InterfaceUtil(object): :rtype: list """ cmd = 'sw_interface_rx_placement_dump' - cmd_reply = 'sw_interface_rx_placement_details' err_msg = "Failed to run '{cmd}' PAPI command on host {host}!".format( cmd=cmd, host=node['host']) - with PapiExecutor(node) as papi_exec: + with PapiSocketExecutor(node) as papi_exec: for ifc in node['interfaces'].values(): if ifc['vpp_sw_index'] is not None: papi_exec.add(cmd, sw_if_index=ifc['vpp_sw_index']) - papi_resp = papi_exec.get_dump(err_msg) - thr_mapping = [s[cmd_reply] for r in papi_resp.reply - for s in r['api_reply']] - return sorted(thr_mapping, key=lambda k: k['sw_if_index']) + details = papi_exec.get_details(err_msg) + return sorted(details, key=lambda k: k['sw_if_index']) @staticmethod def vpp_sw_interface_set_rx_placement(node, sw_if_index, queue_id, @@ -1634,9 +1569,8 @@ class InterfaceUtil(object): "{host}!".format(host=node['host']) args = dict(sw_if_index=sw_if_index, queue_id=queue_id, worker_id=worker_id) - with PapiExecutor(node) as papi_exec: - papi_exec.add(cmd, **args).get_replies(err_msg).\ - verify_reply(err_msg=err_msg) + with PapiSocketExecutor(node) as papi_exec: + papi_exec.add(cmd, **args).get_reply(err_msg) @staticmethod def vpp_round_robin_rx_placement(node, prefix): @@ -1650,6 +1584,8 @@ class InterfaceUtil(object): """ worker_id = 0 worker_cnt = len(VPPUtil.vpp_show_threads(node)) - 1 + if not worker_cnt: + return for placement in InterfaceUtil.vpp_sw_interface_rx_placement_dump(node): for interface in node['interfaces'].values(): if placement['sw_if_index'] == interface['vpp_sw_index'] \