Skip to content

Commit e087292

Browse files
dmarxIOLPatrickRobbIOL
authored andcommitted
dts: add virtio forwarding test suite
Add test suite covering virtio-user/vhost-user server/client forwarding scenarios with testpmd packet validation. Signed-off-by: Dean Marx <[email protected]> Reviewed-by: Patrick Robb <[email protected]>
1 parent e48f2c1 commit e087292

File tree

2 files changed

+205
-0
lines changed

2 files changed

+205
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.. SPDX-License-Identifier: BSD-3-Clause
2+
3+
virtio_fwd Test Suite
4+
=====================
5+
6+
.. automodule:: tests.TestSuite_virtio_fwd
7+
:members:
8+
:show-inheritance:

dts/tests/TestSuite_virtio_fwd.py

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# SPDX-License-Identifier: BSD-3-Clause
2+
# Copyright(c) 2025 University of New Hampshire
3+
4+
"""Virtio forwarding test suite.
5+
6+
Verify vhost/virtio pvp and fully virtual functionalities.
7+
"""
8+
9+
from scapy.layers.inet import IP
10+
from scapy.layers.l2 import Ether
11+
12+
from api.capabilities import LinkTopology
13+
from api.packet import send_packets_and_capture
14+
from api.test import log, verify
15+
from api.testpmd import TestPmd
16+
from api.testpmd.config import PortTopology, SimpleForwardingModes
17+
from framework.test_suite import TestSuite, func_test
18+
from framework.testbed_model.capability import requires
19+
from framework.testbed_model.linux_session import LinuxSession
20+
from framework.testbed_model.virtual_device import VirtualDevice
21+
22+
23+
class TestVirtioFwd(TestSuite):
24+
"""Virtio forwarding test suite."""
25+
26+
virtio_user_vdev = VirtualDevice(
27+
"net_virtio_user0,mac=00:01:02:03:04:05,path=/tmp/vhost-net,server=1"
28+
)
29+
vhost_user_vdev = VirtualDevice("eth_vhost0,iface=/tmp/vhost-net,client=1")
30+
31+
@requires(topology_type=LinkTopology.NO_LINK)
32+
@func_test
33+
def virtio_server(self) -> None:
34+
"""Test virtio server packet transmission.
35+
36+
Steps:
37+
* Launch a testpmd session with a vhost-user virtual device (client side).
38+
* Launch a testpmd session with a virtio-user virtual device (server side).
39+
* Set the forwarding mode to mac in both sessions.
40+
* Start packet forwarding on vhost session.
41+
* Send a burst of packets from the virtio session.
42+
* Stop packet forwarding on vhost session and collect packet stats.
43+
44+
Verify:
45+
* Vhost session receives packets from virtio session.
46+
"""
47+
with (
48+
TestPmd(
49+
prefix="vhost",
50+
no_pci=True,
51+
memory_channels=4,
52+
vdevs=[self.vhost_user_vdev],
53+
) as vhost,
54+
TestPmd(
55+
prefix="virtio",
56+
no_pci=True,
57+
memory_channels=4,
58+
vdevs=[self.virtio_user_vdev],
59+
) as virtio,
60+
):
61+
vhost.set_forward_mode(SimpleForwardingModes.mac)
62+
virtio.set_forward_mode(SimpleForwardingModes.mac)
63+
64+
vhost.start()
65+
virtio.start_tx_first(burst_num=32)
66+
vhost.stop()
67+
68+
vhost_forwarding_stats, vhost_raw_output = vhost.show_port_stats_all()
69+
70+
rx_packets = vhost_forwarding_stats[0].rx_packets
71+
tx_packets = vhost_forwarding_stats[0].tx_packets
72+
73+
log(f"Vhost forwarding statistics:\n{vhost_raw_output}")
74+
75+
verify(
76+
rx_packets != 0 and tx_packets != 0,
77+
"Vhost session failed to receive packets from virtio session.",
78+
)
79+
80+
@requires(topology_type=LinkTopology.NO_LINK)
81+
@func_test
82+
def virtio_server_reconnect(self) -> None:
83+
"""Test virtio server reconnection.
84+
85+
Steps:
86+
* Launch a testpmd session with a vhost-user virtual device (client side).
87+
* Launch a testpmd session with a virtio-user virtual device (server side).
88+
* Close the virtio session and relaunch it.
89+
* Start packet forwarding on vhost session.
90+
* Send a burst of packets from the virtio session.
91+
* Stop packet forwarding on vhost session and collect packet stats.
92+
93+
Verify:
94+
* Vhost session receives packets from relaunched virtio session.
95+
"""
96+
with TestPmd(
97+
prefix="vhost",
98+
no_pci=True,
99+
memory_channels=4,
100+
vdevs=[self.vhost_user_vdev],
101+
) as vhost:
102+
with TestPmd(
103+
prefix="virtio",
104+
no_pci=True,
105+
memory_channels=4,
106+
vdevs=[self.virtio_user_vdev],
107+
) as virtio:
108+
pass
109+
# end session and reconnect
110+
with TestPmd(
111+
prefix="virtio",
112+
no_pci=True,
113+
memory_channels=4,
114+
vdevs=[self.virtio_user_vdev],
115+
) as virtio:
116+
virtio.set_forward_mode(SimpleForwardingModes.mac)
117+
vhost.set_forward_mode(SimpleForwardingModes.mac)
118+
119+
vhost.start()
120+
virtio.start_tx_first(burst_num=32)
121+
vhost.stop()
122+
123+
vhost_forwarding_stats, vhost_raw_output = vhost.show_port_stats_all()
124+
125+
rx_packets = vhost_forwarding_stats[0].rx_packets
126+
tx_packets = vhost_forwarding_stats[0].tx_packets
127+
128+
log(f"Vhost forwarding statistics:\n{vhost_raw_output}")
129+
130+
verify(
131+
rx_packets != 0 and tx_packets != 0,
132+
"Vhost session failed to receive packets from virtio session.",
133+
)
134+
135+
@requires(topology_type=LinkTopology.ONE_LINK)
136+
@func_test
137+
def pvp_loop(self) -> None:
138+
"""Test vhost/virtio physical-virtual-physical topology.
139+
140+
Steps:
141+
* Launch testpmd session with a physical NIC and virtio-user vdev
142+
connected to a vhost-net socket.
143+
* Configure the tap interface that is created with IP address and
144+
set link state to UP.
145+
* Launch second testpmd session with af_packet vdev connected to
146+
the tap interface.
147+
* Start packet forwarding on both testpmd sessions.
148+
* Send 100 packets to the physical interface from external tester.
149+
150+
Verify:
151+
* Vhost session receives/forwards 100+ packets.
152+
"""
153+
self.sut_node = self._ctx.sut_node
154+
if not isinstance(self.sut_node.main_session, LinuxSession):
155+
verify(False, "Must be running on a Linux environment.")
156+
# delete tap0 interface if it exists
157+
self.sut_node.main_session.delete_interface(name="tap0")
158+
with TestPmd(
159+
prefix="virtio",
160+
vdevs=[VirtualDevice("virtio_user0,path=/dev/vhost-net,queues=1,queue_size=1024")],
161+
port_topology=PortTopology.chained,
162+
) as virtio:
163+
self.sut_node.main_session.set_interface_link_up(name="tap0")
164+
with TestPmd(
165+
prefix="vhost",
166+
no_pci=True,
167+
vdevs=[VirtualDevice("net_af_packet0,iface=tap0")],
168+
port_topology=PortTopology.loop,
169+
) as vhost:
170+
virtio.set_forward_mode(SimpleForwardingModes.mac)
171+
vhost.set_forward_mode(SimpleForwardingModes.mac)
172+
173+
portlist_order = [0, 2, 1] if len(virtio.ports) == 3 else [0, 1]
174+
virtio.set_portlist(order=portlist_order)
175+
176+
vhost.start()
177+
virtio.start()
178+
179+
packet = Ether() / IP()
180+
packets = [packet] * 100
181+
send_packets_and_capture(packets)
182+
183+
vhost.stop()
184+
virtio.stop()
185+
186+
vhost_forwarding_stats, vhost_raw_output = vhost.show_port_stats_all()
187+
188+
rx_packets = vhost_forwarding_stats[0].rx_packets
189+
tx_packets = vhost_forwarding_stats[0].tx_packets
190+
191+
log(f"Vhost forwarding statistics:\n{vhost_raw_output}")
192+
193+
verify(
194+
rx_packets >= 100 and tx_packets >= 100,
195+
f"PVP loop forwarding verification failed: vhost interface RX={rx_packets},"
196+
f" TX={tx_packets} (expected ≥100 each).",
197+
)

0 commit comments

Comments
 (0)