X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FInterfaceUtil.py;h=1f79d7e67929fbe6e2491639769db9f58fe1e010;hb=refs%2Fchanges%2F13%2F21113%2F7;hp=6de17d10d90f892b3dcc9024e476b5256be33ea8;hpb=f88a3d9178dfbd73d0479f9aa2f5224e0c89ca1f;p=csit.git diff --git a/resources/libraries/python/InterfaceUtil.py b/resources/libraries/python/InterfaceUtil.py index 6de17d10d9..1f79d7e679 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 @@ -305,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' @@ -324,27 +338,12 @@ class InterfaceUtil(object): with PapiSocketExecutor(node) as papi_exec: details = papi_exec.add(cmd, **args).get_details(err_msg) - 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 - data = list() if interface is None else dict() - for if_dump in details: + for dump in details: if interface is None: - data.append(process_if_dump(if_dump)) - elif str(if_dump.get(param)).rstrip('\x00') == str(interface): - data = process_if_dump(if_dump) + 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)) @@ -711,18 +710,18 @@ 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, @@ -781,6 +780,33 @@ class InterfaceUtil(object): 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): """Get VxLAN data for the given interface. @@ -796,18 +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' - 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) - def process_vxlan_dump(vxlan_dump): """Process vxlan dump. @@ -818,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 vxlan_dump in details: + for dump in details: if interface is None: - data.append(process_vxlan_dump(vxlan_dump)) - elif vxlan_dump['sw_if_index'] == sw_if_index: - data = process_vxlan_dump(vxlan_dump) + 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)) @@ -850,12 +876,6 @@ class InterfaceUtil(object): :returns: List of dictionaries with all vhost-user interfaces. :rtype: list """ - cmd = 'sw_interface_vhost_user_dump' - err_msg = 'Failed to get vhost-user dump on host {host}'.format( - host=node['host']) - with PapiSocketExecutor(node) as papi_exec: - details = papi_exec.add(cmd).get_details(err_msg) - def process_vhost_dump(vhost_dump): """Process vhost dump. @@ -870,65 +890,19 @@ class InterfaceUtil(object): vhost_dump['sock_filename'].rstrip('\x00') return vhost_dump - for vhost_dump in details: - # In-place edits. - process_vhost_dump(vhost_dump) - - logger.debug('Vhost-user details:\n{vhost_details}'.format( - vhost_details=details)) - return details - - @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' - 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 PapiSocketExecutor(node) as papi_exec: details = papi_exec.add(cmd).get_details(err_msg) - 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 tap_dump in details: - if name is None: - data.append(process_tap_dump(tap_dump)) - elif tap_dump.get('dev_name').rstrip('\x00') == name: - data = process_tap_dump(tap_dump) - break + for dump in details: + # In-place edits. + process_vhost_dump(dump) - 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, @@ -1018,18 +992,20 @@ class InterfaceUtil(object): 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 PapiSocketExecutor(node) as papi_exec: @@ -1039,6 +1015,9 @@ class InterfaceUtil(object): 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_index @@ -1182,10 +1161,8 @@ class InterfaceUtil(object): for bond in details: data += ('{b}\n'.format(b=bond['interface_name'].rstrip('\x00'))) - data += (' mode: {m}\n'.format(m=LinkBondMode( - bond['mode']).name.lower())) - data += (' load balance: {lb}\n'.format(lb=LinkBondLoadBalance( - bond['lb']).name.lower())) + 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: @@ -1214,15 +1191,6 @@ class InterfaceUtil(object): :returns: Bond slave interface data. :rtype: dict """ - 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']) - - with PapiSocketExecutor(node) as papi_exec: - details = papi_exec.add(cmd, **args).get_details(err_msg) - def process_slave_dump(slave_dump): """Process slave dump. @@ -1235,9 +1203,18 @@ class InterfaceUtil(object): rstrip('\x00') return slave_dump - for slave_dump in details: + 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']) + + 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(slave_dump) + process_slave_dump(dump) logger.debug('Slave data:\n{slave_data}'.format(slave_data=details)) return details @@ -1340,19 +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' - 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) - def process_vxlan_gpe_dump(vxlan_dump): """Process vxlan_gpe dump. @@ -1363,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 vxlan_dump in details: + for dump in details: if interface_name is None: - data.append(process_vxlan_gpe_dump(vxlan_dump)) - elif vxlan_dump['sw_if_index'] == sw_if_index: - data = process_vxlan_gpe_dump(vxlan_dump) + 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( @@ -1499,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'\:')) @@ -1516,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 = []