X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FVhostUser.py;h=c6b9185e14d3a9cd70cf8f1c34db446b0d870b43;hb=7f138bad98908762f9e738c2d7c47ac204acae71;hp=48cce002bd08c64c6cce370e81b36d8ae3c6d409;hpb=d68951ac245150eeefa6e0f4156e4c1b5c9e9325;p=csit.git diff --git a/resources/libraries/python/VhostUser.py b/resources/libraries/python/VhostUser.py index 48cce002bd..c6b9185e14 100644 --- a/resources/libraries/python/VhostUser.py +++ b/resources/libraries/python/VhostUser.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: @@ -13,55 +13,68 @@ """Vhost-user interfaces library.""" +from enum import IntEnum + from robot.api import logger +from resources.libraries.python.CpuUtils import CpuUtils from resources.libraries.python.PapiExecutor import PapiSocketExecutor from resources.libraries.python.topology import NodeType, Topology from resources.libraries.python.InterfaceUtil import InterfaceUtil +from resources.libraries.python.ssh import exec_cmd_no_error + + +class VirtioFeaturesFlags(IntEnum): + """Virtio Features Flags.""" + VIRTIO_NET_F_API_CSUM = 0 + VIRTIO_NET_F_API_GUEST_CSUM = 1 + VIRTIO_NET_F_API_GSO = 6 + VIRTIO_NET_F_API_GUEST_TSO4 = 7 + VIRTIO_NET_F_API_GUEST_TSO6 = 8 + VIRTIO_NET_F_API_GUEST_UFO = 10 + VIRTIO_NET_F_API_HOST_TSO4 = 11 + VIRTIO_NET_F_API_HOST_TSO6 = 12 + VIRTIO_NET_F_API_HOST_UFO = 14 + VIRTIO_NET_F_API_MRG_RXBUF = 15 + VIRTIO_NET_F_API_CTRL_VQ = 17 + VIRTIO_NET_F_API_GUEST_ANNOUNCE = 21 + VIRTIO_NET_F_API_MQ = 22 + VIRTIO_F_API_ANY_LAYOUT = 27 + VIRTIO_F_API_INDIRECT_DESC = 28 class VhostUser: """Vhost-user interfaces L1 library.""" @staticmethod - def _sw_interface_vhost_user_dump(node): - """Get the Vhost-user dump on the given node. - - :param node: Given node to get Vhost dump from. - :type node: dict - :returns: List of Vhost-user interfaces data extracted from Papi - response. - :rtype: list - """ - cmd = u"sw_interface_vhost_user_dump" - - with PapiSocketExecutor(node) as papi_exec: - details = papi_exec.add(cmd).get_details() - - for vhost in details: - vhost[u"interface_name"] = vhost[u"interface_name"] - vhost[u"sock_filename"] = vhost[u"sock_filename"] - - logger.debug(f"VhostUser details:\n{details}") - - return details - - @staticmethod - def vpp_create_vhost_user_interface(node, socket): + def vpp_create_vhost_user_interface( + node, socket, is_server=False, virtio_feature_mask=None): """Create Vhost-user interface on VPP node. :param node: Node to create Vhost-user interface on. :param socket: Vhost-user interface socket path. + :param is_server: Server side of connection. Default: False + :param virtio_feature_mask: Mask of virtio features to be enabled. :type node: dict :type socket: str + :type is_server: bool + :type virtio_feature_mask: int :returns: SW interface index. :rtype: int """ cmd = u"create_vhost_user_if" err_msg = f"Failed to create Vhost-user interface " \ f"on host {node[u'host']}" + if virtio_feature_mask is None: + enable_gso = False + else: + enable_gso = VirtioFeatureMask.is_feature_enabled( + virtio_feature_mask, VirtioFeaturesFlags.VIRTIO_NET_F_API_GSO + ) args = dict( - sock_filename=str(socket).encode(encoding=u"utf-8") + is_server=bool(is_server), + sock_filename=str(socket), + enable_gso=bool(enable_gso) ) with PapiSocketExecutor(node) as papi_exec: @@ -111,15 +124,6 @@ class VhostUser: """ return InterfaceUtil.vpp_get_interface_mac(node, sw_if_index) - @staticmethod - def vpp_show_vhost(node): - """Get Vhost-user data for the given node. - - :param node: VPP node to get interface data from. - :type node: dict - """ - VhostUser._sw_interface_vhost_user_dump(node) - @staticmethod def show_vpp_vhost_on_all_duts(nodes): """Show Vhost-user on all DUTs. @@ -129,7 +133,7 @@ class VhostUser: """ for node in nodes.values(): if node[u"type"] == NodeType.DUT: - VhostUser.vpp_show_vhost(node) + VhostUser.vhost_user_dump(node) @staticmethod def vhost_user_dump(node): @@ -148,3 +152,62 @@ class VhostUser: logger.debug(f"Vhost-user details:\n{details}") return details + + @staticmethod + def vhost_user_affinity(node, pf_key, skip_cnt=0): + """Set vhost-user affinity for the given node. + + :param node: Topology node. + :param pf_key: Interface key to compute numa location. + :param skip_cnt: Skip first "skip_cnt" CPUs. + :type node: dict + :type pf_key: str + :type skip_cnt: int + """ + pids, _ = exec_cmd_no_error( + node, f"grep -h vhost /proc/*/comm | uniq | xargs pidof") + + affinity = CpuUtils.get_affinity_vhost( + node, pf_key, skip_cnt=skip_cnt, cpu_cnt=len(pids.split(" "))) + + for cpu, pid in zip(affinity, pids.split(" ")): + exec_cmd_no_error(node, f"taskset -pc {cpu} {pid}", sudo=True) + + +class VirtioFeatureMask: + """Virtio features utilities""" + + @staticmethod + def create_virtio_feature_mask(**kwargs): + """Create virtio feature mask with feature bits set according to kwargs. + :param kwargs: Key-value pairs of feature names and it's state + :type kwargs: dict + """ + virtio_feature_mask = 0 + + if u"all" in kwargs and kwargs[u"all"] is True: + for virtio_feature_flag in VirtioFeaturesFlags: + virtio_feature_mask |= 1 << virtio_feature_flag.value + else: + for feature_name, enabled in kwargs.items(): + virtio_feature_name = \ + u"VIRTIO_NET_F_API_" + feature_name.upper() + if virtio_feature_name not in VirtioFeaturesFlags.__members__: + raise ValueError(u"Unsupported virtio feature flag name") + if enabled: + virtio_feature_mask |= \ + 1 << VirtioFeaturesFlags[virtio_feature_name].value + + return virtio_feature_mask + + @staticmethod + def is_feature_enabled(virtio_feature_mask, virtio_feature_flag): + """Checks if concrete virtio feature is enabled within + virtio_feature_mask + :param virtio_feature_mask: Mask of enabled virtio features + :param virtio_feature_flag: Checked virtio feature + :type virtio_feature_mask: int + :type virtio_feature_flag: VirtioFeaturesFlags + """ + feature_flag_bit = 1 << virtio_feature_flag.value + return (virtio_feature_mask & feature_flag_bit) > 0