Skip to content

Commit 9cd25f3

Browse files
committed
Migrate pktgen perf tests from tp-qemu to tp-libvirt
- Add pktgen_perf_test.cfg: new perf test config with tx/rx, multiple scripts, and vhost_vdpa variant (dev_type=vdpa, iface_dict, client, pktgen_tx_dst_mac). - Extend pktgen_burst_mode_test.py: vhost-vdpa setup and session-based verify_dmesg. - Extend pktgen_utils.py: vdpa/rx/client support Signed-off-by: Wenli Quan <[email protected]>
1 parent 0b4c929 commit 9cd25f3

File tree

3 files changed

+147
-22
lines changed

3 files changed

+147
-22
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
- virtual_network.qemu_test.pktgen_perf_test:
2+
type = pktgen_burst_mode_test
3+
no Windows
4+
only virtio_net
5+
no Host_RHEL.m5, Host_RHEL.m6
6+
vm_ping_host = "pass"
7+
pkg_dir = "tx rx"
8+
pktgen_script = "pktgen_sample01_simple pktgen_sample03_burst_single_flow pktgen_sample05_flow_per_thread"
9+
pktgen_threads = 1
10+
pkt_size = 64
11+
burst = 1
12+
pktgen_test_timeout = 30
13+
record_list = pkt_size run_threads burst mpps
14+
guest_ver_cmd = "uname -r"
15+
kvm_ver_chk_cmd = "rpm -qa qemu-kvm-rhev qemu-kvm"
16+
test_vm = no
17+
flush_firewall_rules_cmd = "iptables -F ; nft flush ruleset"
18+
queues_nic1 = "8"
19+
create_vm_libvirt = "yes"
20+
kill_vm_libvirt = "yes"
21+
ovmf:
22+
kill_vm_libvirt_options = " --nvram"
23+
master_images_clone = img1
24+
remove_image_image1 = yes
25+
26+
variants:
27+
- @default:
28+
- vhost_vdpa:
29+
# Run pktgen perf test with vhost-vdpa interface.
30+
# Default intent is VM <-> external host traffic testing.
31+
dev_type = "vdpa"
32+
driver_queues = 9
33+
vm_iface_driver = "virtio_net"
34+
mac_addr = "52:54:00:00:00:00"
35+
iface_dict = {'model': 'virtio', 'source': {'dev': '/dev/vhost-vdpa-0'}, 'type_name': 'vdpa', 'driver': {'driver_attr': {'queues': '${driver_queues}'}}, 'mac_address': mac_addr}
36+
vm_attrs = {'vcpu': 10, 'current_vcpu': 10}
37+
# Please modify the commented-out example values below
38+
# client = ip
39+
# username_client = your_username
40+
# password_client = your_password
41+
# shell_port_client = 22
42+
# shell_client_client = ssh
43+
# shell_prompt_client = [$#%]
44+
# client_pktgen_iface = ethX # external host iface used by pktgen
45+
# pktgen_tx_dst_mac = xx:xx:xx:xx:xx:xx

libvirt/tests/src/virtual_network/qemu/pktgen_burst_mode_test.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@
1212
from avocado.utils import distro
1313
from avocado.utils import process
1414

15+
from virttest import virsh
1516
from virttest import utils_misc
1617
from virttest import utils_net
1718
from virttest.libvirt_xml import vm_xml
19+
from virttest.utils_libvirt import libvirt_vmxml
20+
from virttest.utils_test import libvirt
1821

1922
from provider.virtual_network import pktgen_utils
2023
from provider.virtual_network import network_base
24+
from provider.interface import interface_base
2125

2226

2327
def write_to_result_file(test, params):
@@ -61,10 +65,36 @@ def run_test():
6165
pktgen_utils.install_package(host_ver)
6266

6367
test.log.debug("TEST_STEP 2: Test with guest and host connectivity")
68+
recreate_serial_console = False
69+
# vhost-vdpa needs XML updates before starting VM
70+
if params.get("dev_type") == "vdpa" and params.get("iface_dict"):
71+
# Ensure VM is stopped before XML changes
72+
virsh.destroy(vm_name, debug=True, ignore_status=True)
73+
recreate_serial_console = True
74+
75+
libvirt_vmxml.remove_vm_devices_by_type(vm, "interface")
76+
vm_attrs = eval(params.get("vm_attrs", "{}"))
77+
if vm_attrs:
78+
vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
79+
vmxml.setup_attrs(**vm_attrs)
80+
vmxml.sync()
81+
82+
# Add a single vhost-vdpa interface
83+
vmxml = vm_xml.VMXML.new_from_dumpxml(vm_name)
84+
iface_dict = interface_base.parse_iface_dict(params)
85+
iface_dev = interface_base.create_iface(params.get("dev_type"), iface_dict)
86+
libvirt.add_vm_device(vmxml, iface_dev)
87+
88+
if vm.virtnet:
89+
vm.virtnet[0].mac = params.get("mac_addr")
90+
vm.virtnet[0].nettype = "vdpa"
91+
6492
if not vm.is_alive():
6593
vm.start()
6694
test.log.debug("Test with Guest xml:%s", vm_xml.VMXML.new_from_dumpxml(vm_name))
67-
session = vm.wait_for_serial_login(restart_network=True)
95+
session = vm.wait_for_serial_login(
96+
restart_network=True, recreate_serial_console=recreate_serial_console
97+
)
6898
network_base.ping_check(params, ips, session, force_ipv4=True)
6999

70100
test.log.debug("TEST_STEP 3: Install package and Run pktgen in burst mode.")
@@ -86,7 +116,15 @@ def run_test():
86116
params, result_file, test_vm, vm, session)
87117

88118
test.log.debug("TEST_STEP: Check the guest dmesg without error messages.")
89-
vm.verify_dmesg()
119+
if params.get("dev_type") == "vdpa":
120+
# vhost-vdpa may not have a guest IP (ARP/arping), so vm.verify_dmesg()
121+
# can fail by attempting a network login.
122+
utils_misc.verify_dmesg(
123+
ignore_result=False,
124+
session=session,
125+
)
126+
else:
127+
vm.verify_dmesg()
90128
vm.verify_kernel_crash()
91129

92130
result_file.close()

provider/virtual_network/pktgen_utils.py

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from avocado.utils import process
66

77
from virttest import data_dir
8+
from virttest import remote
89
from virttest import utils_net
910
from virttest import utils_misc
1011
from virttest import utils_package
@@ -25,26 +26,56 @@ def configure_pktgen(
2526
pkt_cate,
2627
vm=None,
2728
session_serial=None,
29+
script=None,
30+
params=None
2831
):
2932
"""
3033
Configure pktgen test environment for different packet categories.
3134
3235
:param pkt_cate: Packet category (tx, rx, loopback)
3336
:param vm: VM instance
3437
:param session_serial: Serial session for guest command execution
38+
:param params: Dictionary with the test parameters
39+
:param script: Script name to execute
3540
:return: Configured PktgenConfig instance
3641
"""
3742
source_path = os.path.join(data_dir.get_shared_dir(), "scripts/pktgen_perf")
43+
params = params or {}
44+
guest_mac = vm.get_mac_address(0)
45+
guest_eth = utils_net.get_linux_ifname(session_serial, guest_mac)
3846

3947
if pkt_cate == "tx":
4048
LOG_JOB.info("test guest tx pps performance")
4149
vm.copy_files_to(source_path, self.dest_path)
42-
guest_mac = vm.get_mac_address(0)
43-
self.interface = utils_net.get_linux_ifname(session_serial, guest_mac)
44-
host_iface = libvirt.get_ifname_host(vm.name, guest_mac)
45-
dsc_dev = utils_net.Interface(host_iface)
46-
self.dsc = dsc_dev.get_mac()
50+
if params.get("pktgen_tx_dst_mac"):
51+
self.dsc = params.get("pktgen_tx_dst_mac")
52+
else:
53+
host_iface = libvirt.get_ifname_host(vm.name, guest_mac)
54+
dsc_dev = utils_net.Interface(host_iface)
55+
self.dsc = dsc_dev.get_mac()
56+
self.interface = guest_eth
4757
self.runner = session_serial.cmd
58+
elif pkt_cate == "rx":
59+
LOG_JOB.info("test guest rx pps performance")
60+
if params.get("client"):
61+
client_ip = params.get("client")
62+
username = params.get("username_client", "root")
63+
password = params.get("password_client")
64+
remote.copy_files_to(
65+
client_ip, "scp", username, password, 22,
66+
source_path, self.dest_path, timeout=600
67+
)
68+
self.interface = params.get("pktgen_rx_iface")
69+
remote_session = remote.remote_login(
70+
"ssh", client_ip, "22",
71+
username, password, r'[$#%]'
72+
)
73+
self.runner = remote_session.cmd
74+
else:
75+
process.run("cp -r %s %s" % (source_path, self.dest_path))
76+
self.interface = libvirt.get_ifname_host(vm.name, guest_mac)
77+
self.runner = process.run
78+
self.dsc = guest_mac
4879
return self
4980

5081
def generate_pktgen_cmd(
@@ -82,44 +113,48 @@ def generate_pktgen_cmd(
82113

83114
if (
84115
session_serial
85-
and self.runner.__name__ == session_serial.cmd.__name__
116+
and self.runner == session_serial.cmd
86117
):
87118
cmd = f"{cmd} &"
88119

89120
return cmd
90121

91122

92-
def run_test(script, cmd, runner, interface, timeout):
123+
def run_test(script, cmd, runner, interface, timeout, session_serial=None, pkt_cate="tx"):
93124
"""
94125
Run pktgen script on remote and gather packet numbers/time and
95126
calculate mpps.
96127
:param script: pktgen script name.
97128
:param cmd: The command to execute the pktgen script
98129
:param runner: The command runner function
99-
:param interface: The network interface used by pktgen.
130+
:param interface: The VM Ethernet interface used to collect packet counters.
100131
:param timeout: The maximum time allowed for the test to run
132+
:param session_serial: Session serial for VM
133+
:param pkt_cate: Packet category (tx/rx), used to select counter type
101134
:return: The calculated MPPS (Million Packets Per Second)
102135
"""
103-
104-
packets = "cat /sys/class/net/%s/statistics/tx_packets" % interface
136+
counter = "rx_packets" if pkt_cate == "rx" else "tx_packets"
137+
packets = "cat /sys/class/net/%s/statistics/%s" % (interface, counter)
105138
LOG_JOB.info("Start pktgen test by cmd '%s'", cmd)
106139
try:
107-
packet_b = runner(packets)
140+
packet_b = session_serial.cmd(packets)
108141
packet_a = None
109142
runner(cmd, timeout)
143+
packet_a = session_serial.cmd(packets)
110144
except aexpect.ShellTimeoutError:
111145
# when pktgen script is running on guest, the pktgen process
112146
# need to be killed.
113-
kill_cmd = (
114-
"kill -9 `ps -ef | grep %s --color | grep -v grep | "
115-
"awk '{print $2}'`" % script
116-
)
117-
runner(kill_cmd)
118-
packet_a = runner(packets)
147+
if session_serial and runner == session_serial.cmd:
148+
kill_cmd = (
149+
"kill -9 `ps -ef | grep %s --color | grep -v grep | "
150+
"awk '{print $2}'`" % script
151+
)
152+
runner(kill_cmd)
153+
packet_a = session_serial.cmd(packets)
119154
except process.CmdError:
120155
# when pktgen script is running on host, the pktgen process
121156
# will be quit when timeout triggers, so no need to kill it.
122-
packet_a = runner(packets)
157+
packet_a = session_serial.cmd(packets)
123158

124159
return "{:.2f}".format((int(packet_a) - int(packet_b)) / timeout / 10 ** 6)
125160

@@ -193,6 +228,8 @@ def run_tests_for_category(
193228
# Get single values for threads and burst instead of looping
194229
threads = params.get("pktgen_threads", "")
195230
burst = params.get("burst", "")
231+
guest_mac = vm.get_mac_address(0)
232+
guest_eth = utils_net.get_linux_ifname(session_serial, guest_mac)
196233

197234
record_line = ""
198235
for record in record_list:
@@ -210,7 +247,7 @@ def run_tests_for_category(
210247
size = params.get("pkt_size", "")
211248
if pkt_cate != "loopback":
212249
pktgen_config = pktgen_config.configure_pktgen(
213-
pkt_cate, vm, session_serial
250+
pkt_cate, vm, session_serial, script=script, params=params
214251
)
215252
exec_cmd = pktgen_config.generate_pktgen_cmd(
216253
script,
@@ -222,14 +259,19 @@ def run_tests_for_category(
222259
burst,
223260
session_serial,
224261
)
262+
pkt_cate_r = None
225263
if exec_cmd:
226264
pkt_cate_r = run_test(
227265
script,
228266
exec_cmd,
229267
pktgen_config.runner,
230-
pktgen_config.interface,
268+
guest_eth,
231269
timeout,
270+
session_serial,
271+
pkt_cate=pkt_cate,
232272
)
273+
else:
274+
pkt_cate_r = None
233275

234276
line = "%s|" % format_result(size)
235277
line += "%s|" % format_result(threads)

0 commit comments

Comments
 (0)