Skip to content

Add vdpa_utils.py #4271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions generic/tests/cfg/netperf.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#numa configration
numa_node = -1
netperf_with_numa = yes
vdpa_add_flows = yes
# configure netperf test parameters, some seconds will be took to
# wait all the clients work, this wait time should be less than
# 0.5 * l, the wait time will augments if you have move
Expand Down
55 changes: 8 additions & 47 deletions generic/tests/netperf.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from avocado.utils import process
from virttest import error_context, remote, utils_misc, utils_net, utils_test, virt_vm

from provider import netperf_base, win_driver_utils
from provider import netperf_base, vdpa_utils, win_driver_utils

LOG_JOB = logging.getLogger("avocado.test")

Expand Down Expand Up @@ -76,52 +76,13 @@ def mtu_set(mtu):
if netdst in br_in_use:
ifaces_in_use = host_bridges.list_iface()
target_ifaces = list(ifaces_in_use + br_in_use)
if (
process.system(
"which ovs-vsctl && systemctl status openvswitch.service",
ignore_status=True,
shell=True,
)
== 0
):
ovs_br_all = netperf_base.ssh_cmd(host, "ovs-vsctl list-br")
ovs_br = []
if ovs_br_all:
for nic in vm.virtnet:
if nic.netdst in ovs_br_all:
ovs_br.append(nic.netdst)
elif nic.nettype == "vdpa":
vf_pci = netperf_base.ssh_cmd(
host,
"vdpa dev show |grep %s | grep -o 'pci/[^[:space:]]*' | "
"awk -F/ '{print $2}'" % nic.netdst,
)
pf_pci = netperf_base.ssh_cmd(
host,
"grep PCI_SLOT_NAME /sys/bus/pci/devices/%s/physfn/uevent |"
" cut -d'=' -f2" % vf_pci,
)
port = netperf_base.ssh_cmd(
host, "ls /sys/bus/pci/devices/%s/net/ | head -n 1" % pf_pci
)
ovs_br_vdpa = netperf_base.ssh_cmd(
host, "ovs-vsctl port-to-br %s" % port
)
cmd = (
f"ovs-ofctl add-flow {ovs_br_vdpa} '"
"in_port=1,idle_timeout=0 actions=output:2'"
)
cmd += (
f"&& ovs-ofctl add-flow {ovs_br_vdpa} '"
"in_port=2,idle_timeout=0 actions=output:1'"
)
cmd += "&& ovs-ofctl dump-flows {}".format(ovs_br_vdpa)
netperf_base.ssh_cmd(host, cmd)
ovs_br.append(ovs_br_vdpa)
for br in ovs_br:
ovs_list = "ovs-vsctl list-ports %s" % br
ovs_port = netperf_base.ssh_cmd(host, ovs_list)
target_ifaces.extend(ovs_port.split() + [br])

add_flows = params.get("vdpa_ovs_add_flows", "yes") == "yes"
ovs_handler = vdpa_utils.OVSHandler(vm)
target_ifaces.extend(
ovs_handler.get_vdpa_ovs_info(add_flows=add_flows, return_ports=True)
)

if vm.virtnet[0].nettype == "macvtap":
target_ifaces.extend([vm.virtnet[0].netdst, vm.get_ifname(0)])
error_context.context("Change all Bridge NICs MTU to %s" % mtu, test.log.info)
Expand Down
132 changes: 132 additions & 0 deletions provider/vdpa_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import logging

from avocado.utils import process
from virttest import openvswitch, utils_net

LOG_JOB = logging.getLogger("avocado.test")


def check_ovs_status():
"""
Check if ovs-vsctl and openvswitch service are installed and running.
:return: True if both are available and running, otherwise False
:rtype: bool
"""
cmd = "which ovs-vsctl && systemctl status openvswitch.service"
return process.system(cmd, ignore_status=True, shell=True) == 0


def get_vf_pci_address(nic_netdst):
"""
Get vf pci address from a given network destination.

:param nic_netdst: Network destination address
:type nic_netdst: str

:return: VF pci address
:rtype: str
"""
cmd = (
"vdpa dev show | grep {0} | grep -o 'pci/[^[:space:]]*' | "
"awk -F/ '{{print $2}}'"
).format(nic_netdst)
return process.system_output(cmd, shell=True).decode().strip()


def get_pf_pci_address(vf_pci):
"""
Get pf pci address using vf pci address.

:param vf_pci: VF pci address
:type vf_pci: str

:return: VF pci address
:rtype: str
"""
cmd = (
"grep PCI_SLOT_NAME /sys/bus/pci/devices/{0}/physfn/uevent | cut -d'=' -f2"
).format(vf_pci)
return process.system_output(cmd, shell=True).decode().strip()


def get_pf_port(pf_pci):
"""
Get the port for the pf pci address.

:param pf_pci: PF pci address
:type pf_pci: str

:return: Port name
:rtype: str
"""
cmd = "ls /sys/bus/pci/devices/{0}/net/ | head -n 1".format(pf_pci)
return process.system_output(cmd, shell=True).decode().strip()


def add_flows_to_ovs_bridge(bridge, ovs):
"""
Add flow rules to the given ovs bridge.

:parma bridge: OVS bridge name
:type bridge: str
:param ovs: OVS instance
:type ovs: OpenVSwitch
"""
utils_net.openflow_manager(
bridge, "add-flow", flow_options="in_port=1,idle_timeout=0,actions=output:2"
)
utils_net.openflow_manager(
bridge, "add-flow", flow_options="in_port=2,idle_timeout=0,actions=output:1"
)
utils_net.openflow_manager(bridge, "dump-flows")


class OVSHandler:
def __init__(self, vm):
self.vm = vm
if check_ovs_status():
self.ovs = openvswitch.OpenVSwitchControl()
else:
self.ovs = None

def get_vdpa_ovs_info(self, add_flows=True, return_ports=True):
"""
Get OVS bridge and port information.

:param add_flows: Whether to add flows rules to the ovs bridge
:type add_flows: bool
:param return_ports: Whether to return port names
:type return_ports: bool

:return: list of target interfaces(bridges and ports) if return_port is Ture,
else empty list
:rtype: list
"""
if not self.ovs:
LOG_JOB.error("Could not find existing Open vSwitch service")
return []

target_ifaces = []

for nic in self.vm.virtnet:
ovs_br = None
if nic.nettype == "vdpa":
vf_pci = get_vf_pci_address(nic.netdst)
pf_pci = get_pf_pci_address(vf_pci)
port = get_pf_port(pf_pci)
manager, ovs_br = utils_net.find_current_bridge(port)
else:
try:
manager, ovs_br = utils_net.find_current_bridge(nic.netdst)
except NotImplementedError:
ovs_br = None
if ovs_br:
if add_flows:
add_flows_to_ovs_bridge(ovs_br, self.ovs)
if return_ports:
if manager:
ports = set(manager.list_ports(ovs_br))
target_ifaces.extend(ports)
target_ifaces.append(ovs_br)

return target_ifaces
1 change: 1 addition & 0 deletions qemu/tests/cfg/vdpa_dpdk.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
enable_guest_iommu = yes
guest_iommu_option = pt
kernel_extra_params_ad = "default_hugepagesz=1G hugepagesz=1G hugepages=10"
vdpa_ovs_add_flows = yes
# Packet Sending Host Configuration
#dsthost = The IP address of the packet sending host
#username_dsthost = Username for the host
Expand Down
6 changes: 5 additions & 1 deletion qemu/tests/vdpa_dpdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from avocado.utils import process
from virttest import remote, utils_misc, utils_net, utils_sriov

from provider import dpdk_utils
from provider import dpdk_utils, vdpa_utils

LOG_JOB = logging.getLogger("avocado.test")

Expand Down Expand Up @@ -62,6 +62,7 @@ def run(test, params, env):
guest_ver_cmd = params["guest_ver_cmd"]
base = params.get("format_base", "12")
fbase = params.get("format_fbase", "2")
add_flows = params.get("vdpa_ovs_add_flows", "yes") == "yes"

session = vm.wait_for_login(timeout=login_timeout, restart_network=True)

Expand All @@ -75,6 +76,9 @@ def run(test, params, env):
result_file.write("### kvm_version : %s\n" % host_ver)
result_file.write("### guest-kernel-ver :%s" % guest_ver)

ovs_handler = vdpa_utils.OVSHandler(vm)
ovs_handler.get_vdpa_ovs_info(add_flows=add_flows, return_ports=False)

dpdk_utils.install_dpdk(params, session)
dpdk_ver = session.cmd_output("rpm -qa |grep dpdk | head -n 1")
result_file.write("### guest-dpdk-ver :%s" % dpdk_ver)
Expand Down